在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
的情况下,其散列值也相同。
有关如何简单的生成一个这样的散列值,将在下一篇博客中说明。