hibernate實體類中爲何要重寫equals與hashcode方法

1.如果想把持久類的實例放入set中(多值關聯時,1對多),建議實現equals和hashcode

2.想重用託管實例時,也要實現equals和hashcode

3.多個字段組合作爲聯合主鍵,必須實現equals和hashcode方法


     這兩個方法都來自於Object對象,根據API文檔查看下原意。(1)public boolean equals(Objectobj),對於任何非空引用值 x 和 y,當且僅當 x 和 y 引用同一個對象時,此方法才返回 true;注意:當此方法被重寫時,通常有必要重寫 hashCode 方法,以維護 hashCode 方法的常規協定,該協定聲明相等對象必須具有相等的哈希碼。(2)public int hashCode() 返回該對象的哈希碼值。支持該方法是爲哈希表提供一些優點,例如,java.util.Hashtable 提供的哈希表。

    我們知道,如果不重寫equals,那麼比較的將是對象的引用是否指向同一塊內存地址,重寫之後目的是爲了比較兩個對象的value值是否相等。特別指出,此時,利用equals比較八大包裝對象(如int,float等)和String類(因爲該類已重寫了equals和hashcode方法)對象時,默認比較的是值,在比較其它對象都是比較的引用地址。那產生了一個問題,爲什麼jdk中希望我們在重寫equals時,非常有必要重寫hashcode呢?

    我的理解是hashcode是用於散列數據的快速存取,如利用HashSet/HashMap/Hashtable類來存儲數據時,都是根據存儲對象的hashcode值來進行判斷是否相同的。這樣如果我們對一個對象重寫了euqals,意思是隻要對象的成員變量值都相等那麼euqals就等於true,但不重寫hashcode,那麼我們再new一個新的對象,當原對象.equals(新對象)等於true時,兩者的hashcode卻是不一樣的,由此將產生了理解的不一致,如在存儲散列集合時(如Set類),將會存儲了兩個值一樣的對象,導致混淆,因此,就也需要重寫hashcode。爲了保證這種一致性,必須滿足以下兩個條件

    (1)當obj1.equals(obj2)爲true時,obj1.hashCode() == obj2.hashCode()必須爲true
    (2)當obj1.hashCode() == obj2.hashCode()爲false時,obj1.equals(obj2)必須爲false

     下面,通過一個簡單的例子來驗證一下。

import java.util.*;

class BeanA {
private int i;

public BeanA(int i) {
   this.i = i;
}

public String toString() {
   return "   " + i;
}

public boolean equals(Object o) {
   BeanA a = (BeanA) o;
   return (a.i == i) ? true : false;
}

public int hashCode() {
   return i;
}

}

public class HashCodeTest {

public static void main(String[] args) {
   HashSet<BeanA> set = new HashSet<BeanA>();
   for (int i = 0; i <= 3; i++){
    set.add(new BeanA(i));
   }
   System.out.println(set);
   set.add(new BeanA(1));
   System.out.println(set.toString());
   System.out.println(set.contains(new BeanA(0)));
   System.out.println(set.add(new BeanA(1)));
   System.out.println(set.add(new BeanA(4)));
   System.out.println(set);

}

}

我們在類BeanA中重寫了equals和hashcode方法,這樣在存儲到HashSet數據集中,將保證不會出現重複的數據;如果把這兩個方法去掉後,那些重複的數據仍會存入HashSet中,這就與HashSet強調的元素唯一性相違背,大家可以把這兩個方法註釋掉再運行一下。

因此,我們就可以理解在一些java類中什麼情況下需要重寫equals和hashcode。比如:在hibernate的實體類中,往往通過一個主鍵(或唯一標識符)來判斷數據庫的某一行,這就需要重寫這兩個方法。因爲,Hibernate保證,僅在特定會話範圍內,持久化標識(數據庫的行)和Java標識是等價的。因此,一旦 我們混合了從不同會話中獲取的實例,如果希望Set有明確的語義,就必 須實現equals() 和hashCode()。


發佈了27 篇原創文章 · 獲贊 2 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章