列表和列表在Groovy相同?
问题1
无论是列表(对象列表)还是List< String> (Strings列表)在Groovy中使用? 在下面的代码示例中,两个列表都是ArrayList(对象的ArrayList).将第二个列表预期为ArrayList< String> (Strings的ArrayList). 当编译类时,Groovy会丢失类型信息,并在编译的类被执行时推断它吗? 实施例1 List untypedList = ["a","b","c"] List<String> typedList = ["a","c"] println "Untyped list List: ${untypedList.getClass()}" println "Typed list List<String>: ${typedList.getClass()}" 输出1 Untyped list List: class java.util.ArrayList Typed list List<String>: class java.util.ArrayList // Would have expected ArrayList<String> 问题2 我本来希望这个行typedList<<下面的示例中的新的整数(1)将失败,因为我试图将一个int放入一个字符串列表中.任何人都可以解释为什么我可以在String类型列表中添加一个int? 输出显示它仍然是一个整数,即它不是即时转换为字符串“1”. 实施例2 List untypedList = ["a","c"] untypedList << new Integer(1) typedList << new Integer(1) // Why does this work? Shouldn't an exception be thrown? println "Types:" println "Untyped list List: ${untypedList.getClass()}" println "Typed list List<String>: ${typedList.getClass()}" println "List contents:" println untypedList println typedList println "Untyped list:" untypedList.each { println it.getClass() } println "Typed list:" typedList.each { println it.getClass() } 输出2 Types: Untyped list List: class java.util.ArrayList Typed list List<String>: class java.util.ArrayList List contents: [a,b,c,1] [a,1] Untyped list: class java.lang.String class java.lang.String class java.lang.String class java.lang.Integer Typed list: class java.lang.String class java.lang.String class java.lang.String class java.lang.Integer 解决方法
在运行Groovy“正常”时,泛型将在编译之前被丢弃,因此只有在源代码中才存在对开发人员的有用提示.
但是,您可以使用@CompileStatic或@TypeChecked来使Groovy符合这些泛型,并在编译时检查事物的类型. 例如,考虑我有以下项目结构: project |---- src | |---- main | |---- groovy | |---- test | |---- ListDelegate.groovy | |---- Main.groovy |---- build.gradle 用代码: 的build.gradle apply plugin: 'groovy' repositories { mavenCentral() } dependencies { compile 'org.codehaus.groovy:groovy-all:2.2.1' } task( runSimple,dependsOn:'classes',type:JavaExec ) { main = 'test.Main' classpath = sourceSets.main.runtimeClasspath } ListDelegate.groovy package test class ListDelegate<T> { @Delegate List<T> numbers = [] } Main.groovy package test class Main { static main( args ) { def del = new ListDelegate<Integer>() del << 1 del << 'tim' println del } } 现在,运行gradle runSimple给我们的输出: :compileJava UP-TO-DATE :compileGroovy :processResources UP-TO-DATE :classes :runSimple [1,tim] BUILD SUCCESSFUL Total time: 6.644 secs 所以你可以看到,泛型被抛弃了,它只是加入了整数和字符串列出了只有整数的列表 现在,如果我们将ListDelegate.groovy更改为: package test import groovy.transform.* @CompileStatic class ListDelegate<T> { @Delegate List<T> numbers = [] } 并再次运行: :compileJava UP-TO-DATE :compileGroovy :processResources UP-TO-DATE :classes :runSimple [1,tim] BUILD SUCCESSFUL Total time: 6.868 secs 我们得到相同的输出!这是因为虽然ListDelegate现在是静态编译的,但我们的Main类仍然是动态的,所以在构造ListDelegate之前仍然会丢弃泛型…所以我们也可以将Main.groovy更改为: package test import groovy.transform.* @CompileStatic class Main { static main( args ) { def del = new ListDelegate<Integer>() del << 1 del << 'tim' println del } } 而现在重新运行毕业生runSimple给我们: :compileJava UP-TO-DATE :compileGroovy startup failed: /Users/tyates/Code/Groovy/generics/src/main/groovy/test/Main.groovy: 10: [Static type checking] - Cannot find matching method test.ListDelegate#leftShift(java.lang.String). Please check if the declared type is right and if the method exists. @ line 10,column 9. del << 'tim' ^ 1 error :compileGroovy FAILED 正如你所期望的那样,没有为我们声明的整数列表添加一个String. 其实你只需要CompileStatic的Main.groovy类,这个错误就会被拿起来,但是我总是喜欢使用它,而不是只需要我. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |