Ler*_*rve 16 groovy list arraylist
问题1
是否在Groovy中使用(List
对象列表)或List<String>
(字符串列表)是无关紧要的?
在下面的代码示例中,两个列表最终都是ArrayList
(对象的ArrayList).本来希望第二个列表是一个ArrayList<String>
(字符串的ArrayList).
Groovy在编译类时是否会丢失类型信息,并在执行编译的类时推断它?
例1
List untypedList = ["a", "b", "c"]
List<String> typedList = ["a", "b", "c"]
println "Untyped list List: ${untypedList.getClass()}"
println "Typed list List<String>: ${typedList.getClass()}"
Run Code Online (Sandbox Code Playgroud)
输出1
Untyped list List: class java.util.ArrayList
Typed list List<String>: class java.util.ArrayList // Would have expected ArrayList<String>
Run Code Online (Sandbox Code Playgroud)
问题2
我原以为typedList << new Integer(1)
下面示例中的行会因异常而失败,因为我正在尝试将一个int
字符串列入.任何人都可以解释为什么我可以添加int
到String
-typed List
?
输出显示它仍然是Integer
,即它不是在运行中转换为String
"1".
例2
List untypedList = ["a", "b", "c"]
List<String> typedList = ["a", "b", "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() }
Run Code Online (Sandbox Code Playgroud)
输出2
Types:
Untyped list List: class java.util.ArrayList
Typed list List<String>: class java.util.ArrayList
List contents:
[a, b, c, 1]
[a, b, c, 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
Run Code Online (Sandbox Code Playgroud)
tim*_*tes 24
当"正常"运行Groovy时,泛型会在编译之前被丢弃,因此只在源代码中存在作为对开发人员有用的提醒.
但是,您可以使用@CompileStatic
或@TypeChecked
使Groovy尊重这些泛型并在编译时检查事物的类型.
作为一个例子,考虑我有以下项目结构:
project
|---- src
| |---- main
| |---- groovy
| |---- test
| |---- ListDelegate.groovy
| |---- Main.groovy
|---- build.gradle
Run Code Online (Sandbox Code Playgroud)
随着代码:
的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
}
Run Code Online (Sandbox Code Playgroud)
ListDelegate.groovy
package test
class ListDelegate<T> {
@Delegate List<T> numbers = []
}
Run Code Online (Sandbox Code Playgroud)
Main.groovy
package test
class Main {
static main( args ) {
def del = new ListDelegate<Integer>()
del << 1
del << 'tim'
println del
}
}
Run Code Online (Sandbox Code Playgroud)
现在,运行gradle runSimple
给我们输出:
:compileJava UP-TO-DATE
:compileGroovy
:processResources UP-TO-DATE
:classes
:runSimple
[1, tim]
BUILD SUCCESSFUL
Total time: 6.644 secs
Run Code Online (Sandbox Code Playgroud)
所以你可以看到,仿制药被扔掉了,它只是工作增加Integers
和Strings
对出List
的所谓只Integers
现在,如果我们ListDelegate.groovy
改为:
package test
import groovy.transform.*
@CompileStatic
class ListDelegate<T> {
@Delegate List<T> numbers = []
}
Run Code Online (Sandbox Code Playgroud)
并再次运行:
:compileJava UP-TO-DATE
:compileGroovy
:processResources UP-TO-DATE
:classes
:runSimple
[1, tim]
BUILD SUCCESSFUL
Total time: 6.868 secs
Run Code Online (Sandbox Code Playgroud)
我们得到相同的输出!! 这是因为虽然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
}
}
Run Code Online (Sandbox Code Playgroud)
现在重新运行gradle 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
Run Code Online (Sandbox Code Playgroud)
正如您所期望的那样,未能将String
我们声明的List 添加到Integer
.
其实,你只需要CompileStatic
在Main.groovy
类和这个错误会有所回升,但我总是喜欢在那里我可以使用它,而不是在哪里,我需要.