2015-11-06 32 views
4

我一直在玩Groovy,並遇到了這個有趣的事情。 檢查長整數列表是否包含特定數字時檢查整數值,但在檢查長整數值時不適用。List.contains長值不會返回預期值(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的實現中有一些問題,以及它使用的比較運算符是什麼? 我可以解決這個問題,但我想知道是否有某些我缺少的東西,或者如果這實際上是有意的行爲?

+1

列表中的元素是整數,您可以通過執行println(list [0] .getClass())來確認。我不確定Groovy如何處理類型註釋,但是如果將列表更改爲'List ',我會得到完全相同的結果,這對我來說似乎很奇怪。 – msandiford

+0

解決方案可以在這裏看到:http://www.groovy-lang.org/differences.html#_multi_methods – Flown

+0

有趣的事情。該行爲與java不同。爲前。 java下的代碼'List list = new ArrayList(); list.add(5);'把'long'放入'list'中,同時在'groovy''整數'中。假設它與運行時沒有類型檢查有關。 – Rumoku

回答

1

這是因爲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 
[...] 

或本預泛型 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.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   
    } 
} 

你得到一個編譯錯誤:

在Groovy 2.0,你可以打開類型檢查/靜態編譯與@groovy.transform.TypeChecked/@groovy.transform.CompileStatic(靜態編譯觸發器也進行類型檢查)

[Static type checking] - Incompatible generic argument types. Cannot assign java.util.List <java.lang.Integer> to: java.util.List <Long> 
0

問題是你用整數初始化列表。只需初始化您的列表中的長整型值:

List<Long> list = [5L, 7L, 3L] 

現在您將得到您的期望。