我們都知道Java語言是完全面向對象的,在java中,所有的對象都是繼承於Object類。Object類中有兩個方法equals、hashCode,這兩個方法都是用來比較兩個對象是否相等的。
在沒有重寫equals方法的時候我們是繼承了Object的equals方法,該方法是用來比較兩個對象的內存地址,顯然我們new了兩個對象內存地址肯定不一樣。
- 對於值對象,==比較的是兩個對象的值
- 對於引用對象,比較的是兩個對象的地址
默認的equals方法同==,一般來說我們的對象都是引用對象,要重寫equals方法。
現在有一個學生對象,有屬性學號跟姓名,現在我新建一個學生對象,又從數據裏查出一個學生對象,這兩個對象的學號跟姓名一樣,那這兩個對象是不是相等呢?一般情況下,除非你有特殊需求要處理,這兩個對象是相等的,可如果用==去比較,返回的結果卻是false。
這時候我們就必須重寫equals方法了。如果學號是主鍵,在equals方法裏,我們認識只要學號相同,就可以返回true。
hashCode方法也是可以用來比較兩個對象是否相等的。但是我們很少使用,應該說是很少直接使用。hashCode方法返回的是一個int值,可以看做是一個對象的唯一編碼,如果兩個對象的hashCode值相同,我們應該認爲這兩個對象是同一個對象。
一般如果使用java中的Map對象進行存儲時,他會自動調用hashCode方法來比較兩個對象是否相等。
所以如果我們對equals方法進行了重寫,建議一定要對hashCode方法重寫,以保證相同的對象返回相同的hash值,不同的對象返回不同的hash值。
如上面的學生例子,如果學號相同,不管姓名不相同,返回的hash值一定要是一樣的,這時我們的hash值只與學號有關。
public class Test {
public static void main(String[] args) {
HashMap hm = new HashMap();
hm.put(new key(1),new value(2));
if(hm.containsKey(new key(1)))
System.out.println(hm.get(new key(1)));
else
System.out.println("dont have such a key");
}
}
你每次new一個新對象出來hashCode值肯定不一樣,所以你拿不到你要的key。
class key {
int i ;
public key(int i) {
this.i = i;
}
public boolean equals(Object obj) {
if(obj instanceof key) {
if(((key)obj).i == i)
return true;
}
return false;
}
public int hashCode() {
return i;
}
}
- 重寫equals方法時需要重寫hashCode方法,主要針對Map、Set等集合類型的使用。
a: Map、Set等集合類型存放的對象必須是唯一的;
b: 集合類型判斷兩個對象是否相等,是先判斷equals是否相等,如果equals返回true,還要再判斷hashCode返回值是否true,只有兩者都返回true,才認爲該兩個對象是相等的。 - 由於Object的hashCode返回是對象的hash值,所以即使equals返回true,集合也可能判定兩個對象不等,所以必須重寫hashCode方法,以保證當equals返回true時,hashCode也返回true,這樣才能使得集合中存放的對象唯一。