我一直在玩Groovy并遇到了这个有趣的事情。 在检查整数值时检查longs列表是否包含特定数字,但在检查长值时则不行。
List<Long> list = [5, 7, 3]
println (5 in list) // true
println (5L in list) // false
int i = 5
long l = 5
println (i in list) // true
println (l in list) // false
Integer i2 = 5
Long l2 = 5
println (i2 in list) // true
println (l2 in list) // false
我在https://groovyconsole.appspot.com/上运行了此代码。这似乎打破了我(或至少非常反直觉)。我希望在List.contains的实现中有一些问题,它使用的是什么比较运算符? 我可以解决这个问题,但我想知道是否有某些我缺失的东西,或者这是否真的是预期的行为?
答案 0 :(得分:2)
这是因为type erasure,即在运行时没有类型信息。由于groovy是一个dynamic language(动态调度,用于使用元对象协议的方法调用等),默认情况下没有类型检查/静态编译。
所以你的groovy代码大致相当于这个groovy代码:
def list = [5, 7, 3]
// no type checking by default, so generics types does not matter due to type erasure
[...]
或此 pre-generics java代码:
List list = new ArrayList();
list.add(5);
list.add(7);
list.add(3);
System.out.println(list.contains(5)); // true
System.out.println(list.contains(5L)); // false
[...]
如果你在java中编译它(使用-Xlint更好),你会得到经典的Unchecked Error Messages。
从groovy 2.0开始,您可以使用@groovy.transform.TypeChecked
/ @groovy.transform.CompileStatic
打开类型检查/静态编译(静态编译触发器也可以进行类型检查):
@groovy.transform.CompileStatic
class Test {
static main(args) {
List<Long> list = [5, 7, 3]
println (5 in list) // true
println (5L in list) // false
int i = 5
long l = 5
println (i in list) // true
println (l in list) // false
Integer i2 = 5
Long l2 = new Long(5)
println (i2 in list) // true
println (l2 in list) // false
}
}
这样就会出现编译错误:
[Static type checking] - Incompatible generic argument types. Cannot assign java.util.List <java.lang.Integer> to: java.util.List <Long>
答案 1 :(得分:0)
问题是您使用整数初始化列表。只需使用长值初始化列表:
List<Long> list = [5L, 7L, 3L]
现在你会得到你所期望的。