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

我一直在玩Groovy并遇到了这个有趣的事情.

检查长整数列表是否包含特定数字在检查整数值时有效,但在检查长值时则无效.

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

最佳答案 这是因为
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>
点赞