1. 程式人生 > >淺析Java中equals()方法和hashCode方法

淺析Java中equals()方法和hashCode方法

今天去面試,總覺得自己什麼都懂了,應該問題不大,當被問到“未重寫的equals()方法和hashCode()方法裡面的內容是什麼?為什麼在重寫equals()方法的同時需要重寫hashCode()方法?”時,說實話,一臉懵逼啊!!!

一、equals()方法

1、什麼時候應該覆蓋Object.equals()方法?

原生的equals方法:
public boolean equals(Object obj) {
    return (this == obj);
}
從程式碼中可以看出,原生的equals方法使用的是“==”來比較的。學過Java的人都應該知道,“==”比較的是記憶體地址,所以原生的equals方法只有在自己與自己比較的時候才會返回true,是嚴格的判斷一個物件是否相等的方法。所以,如果類具有自己特有的“邏輯相等”概念(不同於物件相等的概念),而且超類沒有覆蓋equals()方法以實現期望的行為,這時我們就需要覆蓋equals()方法了(通俗來說,就是在業務系統中,有時候需要的並不是一種嚴格意義上的相等,而是業務上的物件相等。比如:如果兩個物件中的id相等,那麼就認為這兩個物件是相等的)。

2、覆蓋equals方法時,需要遵守的通用約定

  • 自反性
對於任意非null的引用值x,x.equals(x)必須返回true。
  • 對稱性
對於任意非null的引用值x、y,當且僅當y.equals(x)返回true時,x.equals(y)必須返回true。
  • 一致性
對於任意非null的引用值x、y,只要equals方法的比較操作在物件中所用的資訊沒有發生改變,那麼多次呼叫x.equals(y)應該一致的返回true或false。
  • 傳遞性
對於任意非null的引用值x、y、z,如果x.equals(y)返回true,並且y.equals(z)返回true,那麼x.equals(z)必須返回true。
  • 對於任意非null的引用值x,x.equals(null)必須返回false。
二、hashCode()方法 原生的hashCode方法:
public native int hashCode();
在回答為什麼重寫了equals()方法時需要同時重寫hashCode()方法之前,我們先來看一下hashCode()方法在Object規範中的通用約定:
  • 在應用執行期間,只要物件的equals方法的比較操作所用到的資訊沒有被修改,那麼多次呼叫該物件的equals方法應該始終如一的返回同一個整數。在同一個應用程式的多次執行過程中,每次執行equals方法所返回的整數可以不一致。
  • 如果兩個物件使用equals(Object)方法比較是相等的,那麼呼叫這兩個物件中的任意一個物件的hashCode方法都必須產生相同的一個整數結果。
  • 如果兩個物件使用equals(Object)方法比較是不相等的,那麼呼叫這兩個物件中的任意一個物件的hashCode方法,則不一定要產生不同的整數結果。如果給不同的物件產生不同的hash碼,有可能提高散列表效能(比如往HashMap中新增資料時,具體新增到哪個桶中,就是根據(table.length - 1) & hash來計算的)。

所以,根據以上的hashCode通用約定我們就可以知道:如果重寫了equals方法而沒有重新hashCode方法的話,將會違反hashCode通用約定的第二個約束條件:相等的物件必須具有相等的雜湊碼

根據類的equals方法,兩個截然不同的例項在邏輯上有可能是相等的,但是根據Object類的hashCode方法,他們僅僅是兩個沒有任何共同之處的物件。因此,物件的hashCode方法會返回兩個看起來是隨機的整數,而不是根據第二個約定所要求的那樣,返回兩個相等的整數值。