gpt4 book ai didi

list - Groovy中的List和List 是否相同?

转载 作者:行者123 更新时间:2023-12-03 14:39:21 25 4
gpt4 key购买 nike

问题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()}"


输出1

Untyped list List:       class java.util.ArrayList
Typed list List<String>: class java.util.ArrayList // Would have expected ArrayList<String>


问题2

我希望下面的示例中的 typedList << new Integer(1)行会失败,并出现异常,因为我正尝试将 int放入字符串列表中。谁能解释为什么我可以在 int类型的 String中添加 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() }


输出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

最佳答案

当“正常”运行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 = []
}


主槽

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


正如您所看到的,泛型被扔掉了,它只是将 IntegersStrings添加到了 List可能只是 Integers的地方

现在,如果我们将 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
}
}


现在重新运行 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


如您所料,这是无法将 String添加到声明的 Integer列表中的。

实际上,您只需要 CompileStatic Main.groovy类,就会收到此错误,但是我一直喜欢在可能的地方使用它,而不仅仅是在需要的地方使用。

关于list - Groovy中的List和List <String>是否相同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21984360/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com