一、Java Object规范中的描述
我们先看下Java Object规范中关于hashCode方法的描述(注:Java Object规范是指Java中所有类对象都继承的基本规范),覆盖hashCode方法时,必须满足以下几个条件:
如果两个对象的equals方法返回true,则它们的hashCode方法必须返回相同的值;
如果两个对象的equals方法返回false,则它们的hashCode方法可以返回相同的值,也可以返回不同的值;
只要对象的状态没有发生改变,多次调用hashCode方法的结果必须相同。
二、Object类中的实现
我们再来看下原本Object类中对于这两个方法的实现
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
hashCode方法默认使用的是对象的内存地址作为哈希值,因此在不重写该方法的情况下,同一个类的不同对象的哈希值一定是不同的。
equals方法直接使用了“==”做比较,相当于比较的是内存地址是否相同。
所以如果只重写equals方法而不重写hashCode方法,就违反了“如果两个对象的equals方法返回true,则它们的hashCode方法必须返回相同的值”的规定,其实在Object类equals方法上的注解中写有写到,我们看下
这段翻译过来就是:
请注意,每当重写hashCode方法时,通常都需要重写该方法,以便维护hashCode方法的通用约定,该约定规定相等的对象必须具有相等的hashCode。
三、如果重写equals方法时没有重写hashCode方法,会产生什么后果
在使用HashMap、HashSet等集合类时,会出现意想不到的结果。由于这些集合类使用哈希表来存储元素,哈希表使用哈希值来确定元素的位置。如果两个对象的equals方法返回true,但它们的hashCode方法返回不同的哈希值,这些元素将被存储在哈希表的不同位置,无法正常访问和操作这些元素。