2017-04-19 48 views
1

我非常喜歡groovy中的in運算符。但是現在我發現了一個奇怪的行爲。
請參閱以下腳本。原始類型和IN運算符

int x = 1 
long y = 1 

println "x == y   " + (x == y)   // true 
println "x == new Long(y) " + (x == new Long(y)) // true 
println "x in [y]   " + (x in [y])   // false Why? 
println "[y].contains(x) " + [y].contains(x) // false Why? 

in運營商或回報false,雖然這兩個數是相等的。但爲什麼?

我知道一個集合不能包含原始類型,但是x == new Long(y)是正確的。

+1

因爲x是int和Y是長 – dsharew

+0

@dsharew你是正確的,這是不一樣的物體。但'x == y'返回true。 –

+0

是有趣的一點,但事實並非如此。 :) – dsharew

回答

3

爲什麼它不起作用?
因爲xintylong

爲什麼(x == y)返回true?
==操作員使用類型轉換之後,以便(x == y)是一樣的:

(x == (int)y) 

當您在常規使用[]語法常規列表使用ArrayList類的後面。所以in和方法返回取決於方法implementaion:

public boolean contains(Object o) { 
     return indexOf(o) >= 0; 
    } 

正如你可以看到它調用indexOf方法:

public int indexOf(Object o) { 
     if (o == null) { 
      for (int i = 0; i < size; i++) 
       if (elementData[i]==null) 
        return i; 
     } else { 
      for (int i = 0; i < size; i++) 
       if (o.equals(elementData[i])) 
        return i; 
     } 
     return -1; 
    } 

indexOf方法實際上取決於對equals方法的實現對象已通過。

所以,當你說[y].contains(x)x in [y]它將使用Integerequals()方法實現:

public boolean equals(Object obj) { 
     if (obj instanceof Integer) { 
      return value == ((Integer)obj).intValue(); 
     } 
     return false; 
    } 

正如你可以看到它會返回false,如果你不傳遞一個int不管實際價值。

如果說[x].contains(y)y in [x]它將使用Long的equals方法實現:

public boolean equals(Object obj) { 
     if (obj instanceof Long) { 
      return value == ((Long)obj).longValue(); 
     } 
     return false; 
    } 

再次返回false如果參數不是long實例,而不管價值。

作爲進一步的例子此代碼應返回false:

int x = 1 
long y = 1 

x.equals(y) 
+0

感謝您的全面回答,這一切都是正確的。但對我而言,這是一個醜陋的陷阱。例如,在我的日常工作中,如果我檢查一個project-id(long)與「[1,2,3]中的projectId」是否會始終爲false。我必須在[1l,2l,3l]中編寫「projectId」。 –

+0

歡迎你。是的,所有你需要做的是你必須知道你在列表中放入什麼,換句話說,讓你的列表包含本土類型。所以如果你的列表在搜索過程中包含整數,你必須做'''list.contains((int)param)'''如果你的列表在搜索期間包含長整型數據,你必須做'''list.contains((long)param) ''' – dsharew