覆蓋equals時需要遵守的通用約定
在覆蓋equals方法的時候,你必須要遵守它的通用約定。下面是約定的內容,來自Object的規範[JavaSE6]
結合以上要求,得出了以下實現高質量equals方法的訣竅:
1.使用==符號檢查“參數是否爲這個對象的引用”。
2.使用instanceof操作符檢查“參數是否爲正確的類型”。如果不是,則返回false。一般來說,所謂“正確的類型”是指equals方法所在的那個類。
3.把參數轉換成正確的類型。因爲轉換之前進行過instanceof測試,所以確保會成功。
4.對於該類中的每個“關鍵”域,檢查參數中的域是否與該對象中對應的域相匹配。如果這些測試全部成功,則返回true;否則返回false。
5.當編寫完成了equals方法之後,檢查“對稱性”、“傳遞性”、“一致性”。
/** *@Function: Effective Java 8,9 Object通用方法 *@Date: 2014-3-18 */ public class EqualsTest { public static void main(String[] args) { //通過覆蓋equals方法實現特有的"邏輯相等"行爲 System.out.println(new Phone(222,333).equals(new Phone(222,333))); //未覆蓋hashCode導致獲取不到想要的結果 Map map=new HashMap(); map.put(new Phone(222, 333), "April"); System.out.println(map.get(new Phone(222,333))); } } //Effective Java 8,9 Object通用方法 final class Phone { private final short num1; private final short num2; public Phone(int num1,int num2){ this.num1=(short) num1; this.num2=(short) num2; } /** *@Function: 重寫equals以實現特有的"邏輯相等" * 注:instanceof前的參數爲null會直接返回false,所以沒必要顯式判斷null */ @Override public boolean equals(Object o) { if(this==o){ return true; } if(!(o instanceof Phone)){ return false; } Phone p=(Phone)o; return p.num1==num1&&p.num2==num2; } /** *@Function: 覆蓋equals時總要覆蓋hashCode *否則無法結合所有基於散列的集合一起工作(Hashtable,HashMap,HashSet..) */ @Override public int hashCode() { int result=hashCode; if(result==0){ result=17; result=31*result+num1; result=31*result+num2; } hashCode=result; return result; } int hashCode=0; }
覆蓋equals時總要覆蓋hashCode
一個很常見的錯誤根源在於沒有覆蓋hashCode方法。在每個覆蓋了equals方法的類中,也必須覆蓋hashCode方法。如果不這樣做的話,就會違反Object.hashCode的通用約定,從而導致該類無法結合所有基於散列的集合一起正常運作,這樣的集合包括HashMap、HashSet和Hashtable。