长值的List.contains不返回预期值(groovy)

时间:2015-11-06 10:18:18

标签: groovy

我一直在玩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的实现中有一些问题,它使用的是什么比较运算符? 我可以解决这个问题,但我想知道是否有某些我缺失的东西,或者这是否真的是预期的行为?

2 个答案:

答案 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]

现在你会得到你所期望的。