覆蓋equals有時看起來很簡單,可是許多覆蓋方式會產生錯誤。通常來講須要知足如下條件:
java
1:類的每一個實例本質上都是惟一的。eclipse
2:不關心類是否提供了「邏輯相等(logical equality)」的測試功能。 ide
3:超類已經覆蓋了equals,從超類繼承過來的行爲對於子類也是合適的。 測試
4:類是私有的或是包級私有的,能夠肯定他的equals方法永遠不會被調用。this
首先看個例子spa
public final class CaseInsensitiveString { private final String s; public CaseInsensitiveString(String s) { if (s == null) throw new NullPointerException(); this.s = s; } // Broken - violates symmetry! @Override public boolean equals(Object o) { if (o instanceof CaseInsensitiveString) return s.equalsIgnoreCase(((CaseInsensitiveString) o).s); if (o instanceof String) // One-way interoperability! return s.equalsIgnoreCase((String) o); return false; } public static void main(String[] args) { CaseInsensitiveString cis = new CaseInsensitiveString("Polish"); String s = "polish"; System.out.println("cis.equals(s): "+cis.equals(s)); System.out.println("s.equals(cis):"+s.equals(cis)); }
該代碼運行結果: cis.equals(s): true s.equals(cis):false
這個類的equals意圖很好,它企圖與普通的字符串(String)進行互相操做,正如你們所料,cis.equals(s)返回true,由於cis是對象,調用的是CaseInsensitiveString類中的equals。而s.equals(cis)返回false。是由於s字符串,默認它的equals調用的是String類中的equals方法,因此返回false。code
實現高質量equals方法的訣竅: 對象
一、使用==操做符檢查「參數是否爲這個對象的引用」。 繼承
二、使用instanceof操做符檢查「參數是否爲正確的類型」。 ip
三、把參數轉換成正確的類型。
四、對於該類的每一個「關鍵(significant)」域,檢查參數中的域是否與該對象中對應的域相匹配。
這點myeclipse自動生成的並不徹底完美,myeclipse生成以下:
else if (!name.equals(other.name))
return false;
可是,這條是要求你改爲:
else if (name != other.name && !name.equals(other.name))
return false;
五、當你編寫完成了equals方法以後,應該會問本身三個問題:他是否的對稱的、傳遞的、一致的。
(覆蓋equals時總要覆蓋hashcode;不要企圖讓equals方法過於智能;不要將equals聲明中的Object對象替換爲其餘的類型。)
儘可能不要省略@Override。