2017-04-19 87 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