为什么重写equals,就必须重写hashCode
首先得看一下 equals 与 hashCode 在Object中的源码:
public boolean equals(Object obj) {
return (this == obj);
}
/**
*在合理可行的情况下,由类Object定义的hashCode方法确实为不同的对象返回不同的整数。
*(这通常是通过将对象的内部地址转换为整数来实现的,但是java不需要这种实现技术;编程语言)。
*/
public native int hashCode();
hashCode
是一个native
方法,native
关键字表示该方法的实现是用其他语言编写的,通常是 C 或 C++。在这种情况下,hashCode()
方法的实际实现是由 JVM(Java 虚拟机)本身提供的。方法注释中说hashCode
的结果是根据对象的内存地址计算得出的,也就是说只要对象的内存地址不变,那多次hash
出来的值都是一样的。而此时的equals比对规则是通过==
来进行比对的,==
比对实际就是比对两个对象的内存地址,所以Object
中用equals
与hashCode
来比对两个对象是否相同,都是一致的,都是比对的内存地址.现在就可以解释为什么对象重写
equals
,就必须重写hashCode
了。结论: 因为如果你重写了
equals
,改变了equals的比对逻辑,也就是说你重新定义了这个对象的相等逻辑,而不重写hashCode
的话,hashCode
还是沿用Object
中的内存比对,在好多情况下会得到你预料不到的结果。
产生隐异常举例:
看此例子前可以先了解一下hashSet
集合的存储原理。
在hashSet
中对一个元素进行存储是通过调用这个元素对象的 hashCode
方法得到值再对这个值进行hash
得到存储下标的,这里就出现了一个隐性异常,就是你都重写了这个对象的比对规则,而存储时判断相等还是用的内存地址比对,这就会得到你不想得到的存储结果。