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