2009-12-31 90 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

它們具有相同的價值,這就是爲什麼它是真實的。通常等於方法不測試引用是否相等,儘管這是默認行爲。