java中equals和hashCode方法的解析

解析Java對象的equals()和hashCode()的使用函數

前言編碼

 

在Java語言中,equals()和hashCode()兩個函數的使用是緊密配合的,你要是本身設計其中一個,就要設計另一個。在多數狀況 下,這兩個函數是不用考慮的,直接使用它們的默認設計就能夠了。可是在一些狀況下,這兩個函數最好是本身設計,才能確保整個程序的正常運行。最多見的是當 一個對象被加入收集對象(collection object)時,這兩個函數必須本身設計。更細化的定義是:若是你想將一個對象A放入另外一個收集對象B裏,或者使用這個對象A爲查找一個元對象在收集對 象B裏位置的鑰匙,並支持是否容納,刪除收集對象B裏的元對象這樣的操做,那麼,equals()和hashCode()函數必須開發者本身定義。其餘情 況下,這兩個函數是不須要定義的。spa

equals():.net

它是用於進行兩個對象的比較的,是對象內容的比較,固然也能用於進行對象參閱值的比較。什麼是對象參閱值的比較?就是兩個參閱變量的值得比較,咱們 都知道參閱變量的值其實就是一個數字,這個數字能夠當作是鑑別不一樣對象的代號。兩個對象參閱值的比較,就是兩個數字的比較,兩個代號的比較。這種比較是默 認的對象比較方式,在Object這個對象中,這種方式就已經設計好了。因此你也不用本身來重寫,浪費沒必要要的時間。設計

對象內容的比較纔是設計equals()的真正目的,Java語言對equals()的要求以下,這些要求是必須遵循的。不然,你就不應浪費時間:對象

  • 對稱性:若是x.equals(y)返回是「true」,那麼y.equals(x)也應該返回是「true」。
  • 反射性:x.equals(x)必須返回是「true」。
  • 類推性:若是x.equals(y)返回是「true」,並且y.equals(z)返回是「true」,那麼z.equals(x)也應該返回是「true」。
  • 還有一致性:若是x.equals(y)返回是「true」,只要x和y內容一直不變,無論你重複x.equals(y)多少次,返回都是「true」。
  • 任何狀況下,x.equals(null),永遠返回是「false」;x.equals(和x不一樣類型的對象)永遠返回是「false」。

hashCode():
這 個函數返回的就是一個用來進行赫希操做的整型代號,請不要把這個代號和前面所說的參閱變量所表明的代號弄混了。後者不只僅是個代號還具備在內存中才查找對 象的位置的功能。hashCode()所返回的值是用來分類對象在一些特定的收集對象中的位置。這些對象是HashMap, Hashtable, HashSet,等等。這個函數和上面的equals()函數必須本身設計,用來協助HashMap, Hashtable, HashSet,等等對本身所收集的大量對象進行搜尋和定位。

這些收集對象究竟如何工做的,想象每一個元對象hashCode是一個箱子的 編碼,按照編碼,每一個元對象就是根據hashCode()提供的代號納入相應的箱子裏。全部的箱子加起來就是一個HashSet,HashMap,或 Hashtable對象,咱們須要尋找一個元對象時,先看它的代碼,就是hashCode()返回的整型值,這樣咱們找到它所在的箱子,而後在箱子裏,每 個元對象都拿出來一個個和咱們要找的對象進行對比,若是兩個對象的內容相等,咱們的搜尋也就結束。這種操做須要兩個重要的信息,一是對象的 hashCode(),還有一個是對象內容對比的結果。

hashCode()的返回值和equals()的關係以下:blog

  • 若是x.equals(y)返回「true」,那麼x和y的hashCode()必須相等。
  • 若是x.equals(y)返回「false」,那麼x和y的hashCode()有可能相等,也有可能不等。


爲何這兩個規則是這樣的,緣由其實很簡單,拿HashSet來講吧,HashSet能夠擁有一個或更多的箱子,在同一個箱子中能夠有一個 或更多的獨特元對象(HashSet所容納的必須是獨特的元對象)。這個例子說明一個元對象能夠和其餘不一樣的元對象擁有相同的hashCode。可是一個 元對象只能和擁有一樣內容的元對象相等。因此這兩個規則必須成立。

設計這兩個函數所要注意到的:
若是你設計的對象類型並不使用於收集性對象,那麼沒有必要本身再設計這兩個函數的處理方式。這是正確的面向對象設計方法,任何用戶一時用不到的功能,就先不要設計,以避免給往後功能擴展帶來麻煩。內存

若是你在設計時想別出心裁,不遵照以上的兩套規則,那麼勸你仍是不要作這樣想入非非的事。我尚未遇到過哪個開發者和我說設計這兩個函數要違背前面說的兩個規則,我碰到這些違反規則的狀況時,都是做爲設計錯誤處理。開發

當一個對象類型做爲收集型對象的元對象時,這個對象應該擁有本身處理equals(),和/或處理hashCode()的設計,並且要遵照前面所說 的兩種原則。equals()先要查null和是不是同一類型。查同一類型是爲了不出現ClassCastException這樣的異常給丟出來。查 null是爲了不出現NullPointerException這樣的異常給丟出來。get

若是你的對象裏面容納的數據過多,那麼這兩個函數 equals()和hashCode()將會變得效率低。若是對象中擁有沒法serialized的數據,equals()有可能在操做中出現錯誤。想象 一個對象x,它的一個整型數據是transient型(不能被serialize成二進制數據流)。然而equals()和hashCode()都有依靠 這個整型數據,那麼,這個對象在serialization以前和以後,是否同樣?答案是不同。由於serialization以前的整型數據是有效的 數據,在serialization以後,這個整型數據的值並無存儲下來,再從新由二進制數據流轉換成對象後,二者(對象在serialization 以前和以後)的狀態已經不一樣了。這也是要注意的。

轉自:http://blog.csdn.net/richardsundusky/article/details/1508028

相關文章
相關標籤/搜索