equals和hashCode解析

覆蓋equals時需要遵守的通用約定 
  覆蓋equals方法看起來似乎很簡單,但是如果覆蓋不當會導致錯誤,並且後果相當嚴重。《Effective Java》一書中提到“最容易避免這類問題的辦法就是不覆蓋equals方法”,這句話貌似很搞笑,其實想想也不無道理,其實在這種情況下,類的每個實例都只與它自身相等。如果滿足了以下任何一個條件,這就正是所期望的結果: 
  • 類的每個實例本質上都是唯一的。對於代表活動實體而不是值的類來說卻是如此,例如Thread。Object提供的equals實現對於這些類來說正是正確的行爲。
  • 不關心類是否提供了“邏輯相等”的測試功能。假如Random覆蓋了equals,以檢查兩個Random實例是否產生相同的隨機數序列,但是設計者並不認爲客戶需要或者期望這樣的功能。在這樣的情況下,從Object繼承得到的equals實現已經足夠了。
  • 超類已經覆蓋了equals,從超類繼承過來的行爲對於子類也是合適的。大多數的Set實現都從AbstractSet繼承equals實現,List實現從AbstractList繼承equals實現,Map實現從AbstractMap繼承equals實現。
  • 類是私有的或者是包級私有的,可以確定它的equals方法永遠不會被調用。在這種情況下,無疑是應該覆蓋equals方法的,以防止它被意外調用:@Override 
    public boolean equals(Object o){ 
      throw new AssertionError(); //Method is never called 
    } 


  在覆蓋equals方法的時候,你必須要遵守它的通用約定。下面是約定的內容,來自Object的規範[JavaSE6] 
  • 自反性。對於任何非null的引用值x,x.equals(x)必須返回true。
  • 對稱性。對於任何非null的引用值x和y,當且僅當y.equals(x)返回true時,x.equals(y)必須返回true
  • 傳遞性。對於任何非null的引用值x、y和z,如果x.equals(y)返回true,並且y.equals(z)也返回true,那麼x.equals(z)也必須返回true。
  • 一致性。對於任何非null的引用值x和y,只要equals的比較操作在對象中所用的信息沒有被修改,多次調用該x.equals(y)就會一直地返回true,或者一致地返回false。
  • 對於任何非null的引用值x,x.equals(null)必須返回false。

  結合以上要求,得出了以下實現高質量equals方法的訣竅: 
1.使用==符號檢查“參數是否爲這個對象的引用”。如果是,則返回true。這只不過是一種性能優化,如果比較操作有可能很昂貴,就值得這麼做。 
2.使用instanceof操作符檢查“參數是否爲正確的類型”。如果不是,則返回false。一般來說,所謂“正確的類型”是指equals方法所在的那個類。 
3.把參數轉換成正確的類型。因爲轉換之前進行過instanceof測試,所以確保會成功。 
4.對於該類中的每個“關鍵”域,檢查參數中的域是否與該對象中對應的域相匹配。如果這些測試全部成功,則返回true;否則返回false。 
5.當編寫完成了equals方法之後,檢查“對稱性”、“傳遞性”、“一致性”。 
注意: 
  • 覆蓋equals時總要覆蓋hashCode 《Effective Java》作者說的
  • 不要企圖讓equals方法過於只能。
  • 不要將equals聲明中的Object對象替換爲其他的類型(因爲這樣我們並沒有覆蓋Object中的equals方法哦)


覆蓋equals時總要覆蓋hashCode 
  一個很常見的錯誤根源在於沒有覆蓋hashCode方法。在每個覆蓋了equals方法的類中,也必須覆蓋hashCode方法。如果不這樣做的話,就會違反Object.hashCode的通用約定,從而導致該類無法結合所有基於散列的集合一起正常運作,這樣的集合包括HashMap、HashSet和Hashtable。 
  • 在應用程序的執行期間,只要對象的equals方法的比較操作所用到的信息沒有被修改,那麼對這同一個對象調用多次,hashCode方法都必須始終如一地返回同一個整數。在同一個應用程序的多次執行過程中,每次執行所返回的整數可以不一致。
  • 如果兩個對象根據equals()方法比較是相等的,那麼調用這兩個對象中任意一個對象的hashCode方法都必須產生同樣的整數結果。
  • 如果兩個對象根據equals()方法比較是不相等的,那麼調用這兩個對象中任意一個對象的hashCode方法,則不一定要產生相同的整數結果。但是程序員應該知道,給不相等的對象產生截然不同的整數結果,有可能提高散列表的性能。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章