1. 程式人生 > 實用技巧 >測試物件的等價性——"=="和"equals"

測試物件的等價性——"=="和"equals"

關係運算符== 和 !=也適用於物件。看下面這個例子:

public static void main(String[] args) {
        Integer i = new Integer(1);
        Integer j = new Integer(1);
        System.out.println(i==j); //輸出false
        System.out.println(i!=j); //輸出true
}

i的值明明等於j的值,為什麼會輸出flase?因為 ==和!=比較的是引用所指的物件是否相同。i == j表達的意思是:i這個引用指向的物件和j這個引用指向的物件是相同的嗎?i這個引用指向Integer的一個物件,j這個引用指向Integer的另一個物件。所以會輸出false。
下面我們將程式碼修改,加以驗證。

public static void main(String[] args) {
        Integer i = new Integer(3);
        Integer j = new Integer(1);
        i = j;      //我們讓其發生"別名現象",使i這個引用和j這個引用都指向j引用所指的物件。這樣它們所指的物件就相同了
        System.out.println(i==j);  //輸出true
}

那麼怎樣才能比較兩個物件的內容是否相同呢?這時必須使用所有物件都適用的特殊方法equals()。它是Object類中定義的方法,因為Java中所有的類都繼承於Object,因此所有的類都有這個方法。

public static void main(String[] args) {
        Integer i = new Integer(1);
        Integer j = new Integer(1);
        System.out.println(i.equals(j)); //輸出true
}

然而事情並不總是這麼簡單,假設你建立了自己的類:

class Value{
    int i;
}

public class Sum {
    public static void main(String[] args) {
      Value value1 = new Value();
      Value value2 = new Value();
      value1.i = value2.i = 100;
      System.out.println(value1.equals(value2));//輸出false
    }
}

這又是怎麼回事呢?
上面已經提到了所有類都繼承於Object,我們新建的Value類也不例外,儘管表面上它沒有定義任何方法,實際上它從Object哪裡繼承了許多方法,而equals()就是其一。
至於結果為什麼會是false,這和Object類中equals()方法的實現有關,我們來看看原始碼:

  public boolean equals(Object obj) {
        return this == obj;
    }

結果顯而易見,equals()預設行為比較的是引用是否指向同一個物件。
那麼問題又來了?
為什麼Integer的物件呼叫equals()就能得出正確答案呢?這是因為Integer類重寫了equals()方法。所以要想得到我們希望的行為,除非在自己的新類中重寫equals()方法。