首先从源码的角度来看一看equals()方法的hashcode()方法的含义
equals()方法和hashcode()方法都属于Object类,在Java中,所有的类都是Object类的子类,也就是说,任何Java对象都可调用Object类的方法。
equals()方法:
public boolean equals(Object obj) {
return (this == obj);
}
很明显,该方法就是用来判断两个对象是否是同一个对象。在Object类源码中,其底层是使用了“==”来实现,也就是说通过比较两个对象的内存地址是否相同判断是否是同一个对象,实际上,该equals()方法通常没有太大的实用价值。而我们往往需要用equals()来判断 2个对象在逻辑上是否等价,而非验证它的唯一性。这样我们在实现自己的类时,就要重写equals()方法。
hashcode()方法:
public native int hashCode();
一提到hashcode,很自然就想到哈希表。将某一key值映射到表中的一个位置,从而达到以O(1)的时间复杂度来查询该key值。Object类源码中,hashCode()是一个native方法,哈希值的计算利用的是内存地址。
我们看一下Object类中关于hashCode()方法的注释
1.在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
2.如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
3.如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
通俗的讲,注释中第二点和第三点的含义就是equals()和hashcode()方法要保持相当程度的一致性,equals()方法相等,hashcode()必须相等;反之,equals方法不相等,hashcode可以相等,可以不相等。但是两者的一致有利于提高哈希表的性能。
所以,源码注释来看,两方法的同时重写是很必要的。
实际来看,不同时重写如何?
equals()相等的的两个等价对象因为hashCode不同,所以在hashmap中的table数组的下标不同,从而这两个对象就会同时存在于集合中,在调用hashmap集合中的方法时就会出现逻辑的错误,也就是,你的equals()方法也“白白”重写了。
因此,对于“为什么重写equals()就一定要重写hashCode()方法?”这个问题应该是有个前提,就是你需要用到HashMap,HashSet等Java集合。用不到哈希表的话,其实仅仅重写equals()方法也可以吧。而工作中的场景是常常用到Java集合,所以Java官方建议重写equals()就一定要重写hashCode()方法。