为什么重写equals
要重写hashCode
一、hashCode
在阅读下面的内容之前,大家可能需要先了解一下什么是哈希表、哈希函数,这是数据结构相关的知识。
hashCode
即散列码。散列码是用一个int值来代表对象,它是通过将该对象的某些信息进行转换而生成的。
Object类中默认的hashCode
方法如下。
public native int hashCode();
这是一个本地方法,不同的虚拟机有不同的实现(具体实现自己看虚拟机源码哈)。Object默认的hashCode
是根据对象的内存地址转化而来的,它是唯一的。
我们可以在自己的类中覆盖hashCode
方法,但我们可以使用System.identityHashCode(Object x)
方法返回默认的hashcode
,无论对象是否覆盖默认的hashcode
。
总的来说hashCode
就是获取一个哈希值
二、equals
hashCode
并不需要唯一性,但equals必须严格地判断两个对象是否相同。
正确的equals方法有如下特性:
-
自反性:
x.equals(x)
一定返回true -
对称性:如果
x.equals(y)
为true,那么y.equals(x)
也为true -
传递性:如果
x.equals(y)
为true、y.equals(z)
为true,那么x.equals(z)
也为true -
一致性:如果x和y中用于等价比较的信息没有改变,那么
x.equals(y)
无论调用多少次,结果都一致
任何不是null的x,x.equals(null)
一定返回false
总的来说equals就是比较两个值是否相同
三、equals与hashCode
的相关规定
之所以有规定,是为了使诸如HashMap
这样的哈希表正常使用。具体规定如下:
-
equals相等,
hashcode
一定相等。 -
equals不等,
hashcode
不一定不等。 -
hashcode
不等,equals一定不等。 -
hashcode
相等,equals不一定相等。
因此,如果我们重写了equals,那么必须重写hashCode
,使其满足这些规定。当然,如果我们不把自定义对象当成HashMap
的键来使用,那么自定义对象不重写equals和hashCode
也是可以的。