2009-12-31 91 views
1

我有以下测试程序。我创建了3 Integer引用。我创建了2 Integer对象,并使引用i1和i2分别引用它们。我把参考i3等于i1。现在i1等于()i3应该显然是正确的,因为它们都指向堆上的同一个对象。但为什么i1应该等于()到i2?他们指的是两个不同的对象。我错过了什么。java的equals()方法

documentation说:

 
public boolean equals(Object obj) 
    Indicates whether some other object is "equal to" this one. 


public class Test{ 

    public static void main(String [] args) 
    { 
     Integer i1 = new Integer(10); 
     Integer i2 = new Integer(10); 
     Integer i3 = i1; 

     if(i1.equals(i3)) // UNDERSTANDABLE 
      System.out.println("equal"); 

     if(i1.equals(i2)) // prints equal. WHY !!!!! 
      System.out.println("equal");  
} 

} 
+0

equals是您可以读取源的方法。看看Integer.equals(),那会回答你的问题。 – 2009-12-31 19:57:16

回答

12

equals()方法包装类型的测试值相等,如果你想测试参考平等,使用==代替,例如

System.out.println(new Integer(1) == new Integer(1)); 
3

Integer类的equals方法比较Integer包装的int值。由于10等于10,所以i1和i2被认为是相等的。

5

equals是相等的值版本。类将重写此方法来定义值相等的含义。例如,要查看两个字符串是否包含相同的字符序列,可以使用.equals()方法。如果要创建自己的班级,并且想要将其添加到HashMap,则必须同时定义hashCode()equals()方法才能正常工作。

要查看两个引用是否指向相同的内存位置,请使用==

+1

在自动复制值中使用==会变得更加微妙 - 如果两个Integer对象具有相同的值并且在-128 <= x <= 127范围内,则它们将引用同一个对象。检查了这一点:http://bexhuff.com/2006/11/java-1-5-autoboxing-wackyness – JohnE 2009-12-31 16:40:37

+0

嘿,真棒。这就是为什么原始类型是失败的原因。 – Claudiu 2009-12-31 17:25:30

4

因为i1和i2具有相同的值。 Integer.equals()是这样实现的:

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

所以i1和i2是整数,它们具有相同的值,所以它将返回true。

2

这是equals()Integer实现:

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

考虑到这一点,如果i1的value为10,和i2的value也是10,那么10 == 10将返回true。 。

3

通过查看Integer类,您可能会更好地了解原因。这里是代码低于

/** 
* Compares this object to the specified object. The result is 
* <code>true</code> if and only if the argument is not 
* <code>null</code> and is an <code>Integer</code> object that 
* contains the same <code>int</code> value as this object. 
* 
* @param obj the object to compare with. 
* @return <code>true</code> if the objects are the same; 
*   <code>false</code> otherwise. 
*/ 
public boolean equals(Object obj) { 
if (obj instanceof Integer) { 
    return value == ((Integer)obj).intValue(); 
} 
return false; 
2

如果您在JavaDoc进一步阅读,它提供了更多的细节,特别是:

指示某个其他对象是否 “等于”这一项。等号 方法实现对非空对象 引用一个等价 关系:

  • 自反性:对于任何非空引用值x,x.equals(x)的应 返回真。
  • 它是对称的:对于任何非空引用值x和y,当且仅当 y.equals(x)返回true时,x.equals(y) 应该返回true。
  • 传递性:对于任何非空引用值x,y和z,如果 x.equals(y)的返回true并且 y.equals(z)返回真,则 x.equals(z)的应该返回true。
  • 它是一致的:对于任何非空引用值x和y,多发性 调用x.equals的(y)的 始终返回true或 始终返回false,提供在不使用 信息等于在对象上比较 被修改。
  • 对于任何非空引用值x,x.equals(null)应该返回false。

具体而言,它是由的实现器“等于(对象)”来决定两个对象是否“相等”。作为参考比较,我们使用其他人指出的==运营商。

如果您对此(以及其他类似主题)感兴趣,我也鼓励您阅读Effective Java

1

你的问题的答案已经说过了,但我有一个说明。要小心,因为你自己的对象是从Object扩展的,并且有如操作符==那样实现的方法equal(),所以如果你想比较值,你必须覆盖它。

0

另外请注意,“使用new Integer(int)保证总会产生一个新对象,而Integer.valueOf(int)允许缓存由编译器,类库或JVM完成的值。使用缓存值可以避免对象分配,代码将会快点吧。“ - FindBugs

比较这些语句:

System.out.println("new == " + (new Integer(1) == new Integer(1))); 
System.out.println("new equals() " + new Integer(1).equals(new Integer(1))); 
System.out.println("valueOf() == " 
    + (Integer.valueOf(1) == Integer.valueOf(1))); 
System.out.println("valueOf() equals() " 
    + Integer.valueOf(1).equals(Integer.valueOf(1))); 

其产生这样的输出:

 
new == false 
new equals() true 
valueOf() == true 
valueOf() equals() true 
1

它们具有相同的价值,这就是为什么它是真实的。通常等于方法不测试引用是否相等,尽管这是默认行为。