在Java的Object
的規範中,有一點說的是—— 相等的對象必須有相等的散列碼(hashCode
)
通俗的說就是如果兩個對象通過equals()
方法比較得到的結果是相等的,那麼這兩個對象的hashCode
就一定是相等的。
如果我們重寫了一個對象的equals()
方法的時候沒有重寫其相應的hashCode()
方法,就會違反這一約定,如下的測試代碼
package com.blog.effective.note9;
/**
* 〈一個簡單的電話號碼類〉<br>
*
* @author 未緒
* @time 2018/1/2 15:50
*/
public class PhoneNumber {
private static String phoneNumber; //電話號碼
private static String numAddr; //電話號碼的歸屬地
public PhoneNumber(String phoneNumber,String numAddr){
this.phoneNumber=phoneNumber;
this.numAddr=numAddr;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof PhoneNumber){
PhoneNumber phoneNumber=(PhoneNumber)obj;
return this.phoneNumber==phoneNumber.phoneNumber&&this.numAddr==phoneNumber.numAddr;
}
return false;
}
}
如上是一個簡單的有段電話號碼類,其中包含號碼(phoneNumber
)和歸屬地(numAddr
)兩個屬性,並且我們重寫了它的equals()
方法
我們來測試一下
public static void main(String[] args) {
PhoneNumber phoneNumber1 = new PhoneNumber("123", "FZ");
PhoneNumber phoneNumber2 = new PhoneNumber("123", "FZ");
System.out.println(phoneNumber1.hashCode()); //621009875
System.out.println(phoneNumber2.hashCode()); //1265094477
System.out.println(phoneNumber1.equals(phoneNumber2));//true
}
看到輸出就知道這是違反了開始所說的Object
類的通用約定。
那麼如果就像上面這樣寫會有什麼危害呢?—— 無法與所有的基於散列的集合一起正常使用
如下我們要實現一個根據電話號碼來查詢相關的用戶的功能
HashMap<PhoneNumber, String> hashMap = new HashMap<>();
PhoneNumber number = new PhoneNumber("123", "FZ");
hashMap.put(number,"張三");
hashMap.get(new PhoneNumber("123","FZ"));
按照道理來說我們期望的返回結果是張三
,然而實際運行的結果確實null
這就是因爲這兩者的hashCode
是不相同的,所以從基於散列的集合中查詢不到數據。
所以我們就要根據當前類的屬性值來生成其對應的hashCode
,確保當equals()
方法返回的爲true
的情況下,其散列值也相同。
有關如何簡單的生成一個這樣的散列值,將在下一篇博客中說明。