为什么重写了equals的时候也要重写hashCode

420 阅读3分钟
先看问题

1.为什么重写了equals的时候也要重写hashCode?

先认识一个equals和hashCode

在java的超级父类中(object)存在equals方法和hashCode()方法

image.png

image.png

Object类在java.lang包下,是所有类的根。任何类的对象,都可以调用Object类中的方法。自然而然,如果你没有重写equal()方法和hashCode()方法,就是执行Object中的原始方法。


Object类中的hashCode()方法,用的是native关键字修饰,说明这个方法是个原生函数,也就说这个方法的实现不是用java语言实现的,是使用c/c++实现的,并且被编译成了DLL,由java去调用,jdk源码中不包含。对于不同的平台它们是不同的,java在不同的操作系统中调用不同的native方法实现对操作系统的访问,因为java语言不能直接访问操作系统底层,因为它没有指针。

(1)这种方法调用的过程:

1、在java中申明native方法,然后编译; 

2、用javah产生一个 .h 文件; 

3、写一个 .cpp文件实现native导出方法,其中需要包含第二步产生的.h文件(其中又包含了jdk带的jni.h文件); 

4、将.cpp文件编译成动态链接库文件; 

5、在java中用System.loadLibrary()文件加载第四步产生的动态链接库文件,然后这个navite方法就可被访问了 

hashCode的通用约定

1.在应用程序的执行期间,只要对象的equals()方法的比较操作所用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法都必须始终如一地返回同一个整数,在同一个应用程序的多次执行过程中,每次执行所返回的整数可以不一致。


2.如果两个对象根据equals(object)方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode方法,都必须产生同样的整数结果。


3.如果两个对象根据equals(object)方法比较是不相等的,那么调用这两个对象中任意一个对象的hashCode方法,则不一定会产生不同的整数结果。

只覆盖equals方法,不重写hashCode会 怎么样

PhoneNumber.java

image.png

Test1.java

image.png

从Map中get得到的结果是null,并不是Jenny。

分析一下

这里涉及了两个PhoneNumber的实列:第一个被用于插入HashMap中的phoneNumber1,第 二个实列phoneNumber2被用于获取,第一个实例和第二个是相等的。但是由于

PhoneNumber类没有覆盖hashCode()方法,导致两个实例具有不相等的散列码,违反了hashCode的约定。put方法号码对象存放了一个散列桶中,而get方法确在另外一个散列桶中查找这个号码。

如何解决这个问题

很简单,在PhoneNnumber类中重写hashCode()方法

在PhoneNnumber类中加上如下代码:

image.png


看运行结果:

image.png

如何实现一个好的散列函数?后面在细说。

关注 51码农网 www.51manong.com 寻找一起进步的小伙伴

关注公众号:51码农网

51码农公众平台.jpg