讓我在熱血沸騰中度此一生,讓我在醇酒般的幻夢里醉沉!莫使我眼見這泥塑的肉身,終以空虛的軀殼毀于泥塵!
我們知道,equals()函數(shù)是用來做比較的。java中的比較有兩種:一種是內(nèi)存地址的比較,一種是內(nèi)容的比較。而比較個體也有兩種:一種是簡單類型(這類簡單說來無所謂內(nèi)存地址的比較或者內(nèi)容比較的區(qū)別);還有一種是對象的比較,本文中說的主要是后者
在java中,(對象)內(nèi)存地址的比較,是通過==完成的。比如
這樣的語句中,我們認(rèn)為,如果obj1和obj2的內(nèi)存地址相同,則返回true
而equals()通常是比較內(nèi)容的。這里說“通常” ,是因為在最根本的Object類中,equal()函數(shù)做的是地址的比較。而在其他幾乎所有的類中,equals()都經(jīng)過重載,進(jìn)行內(nèi)容的比較。
而在說equals()的時候我們還涉及hashCode()是因為在有些應(yīng)用中(比如,HashMap的key是對象),必須在重載equals()的同時重載hashCode()。因為java中默認(rèn)(Object)的hashCode是根據(jù)對象的地址計算得到的。
我們通常不會注意到這個問題,因為我們通常所使用的key都是簡單類型,或者是String, Long等一些特殊的對象(其特殊性請參看筆者在寫java 淺拷貝和深拷貝時的討論),這時候,這個問題被我們無意間繞過了
有人已經(jīng)概括了這種我們忽略了的情況:“如果你想將一個對象A放入另一個收集(集合)對象B里,或者使用這個對象A為查找一個元對象在收集對 象B里位置的鑰匙(key),并支持是否容納(isContains()),刪除收集對象B里的元對象(remove()?)這樣的操作,那么,equals()和hashCode()函數(shù)必須開發(fā)者自己定義。” (括號為筆者添加)
為了便于理解,舉一段程序為例:
這段代碼的結(jié)果是什么?答案是nullPointerExcetpion.
而把hashCode()的注釋去除,程序就可以返回正確的結(jié)果了。為什么呢?因為:
Map.put(key,value)時根據(jù)key.hashCode生成一個內(nèi)部hash值,根據(jù)這個hash值將對象存放在一個table中
Map.get(key)會比較key.hashCode和equals方法,當(dāng)且僅當(dāng)這兩者相等時,才能正確定位到table。而我們說過,默認(rèn)的java是對地址進(jìn)行比較的。