写了多年 Java 的你,如果被问到: equals和hashCode为什么要同时重写呢? 你有信心能完整地回答上来吗?
不得不说这是一个很基础的问题,但又不失为一个经典的面试题。 如果在面试中真碰到这个问题,我想有可能会有很多小伙伴儿们栽在这个问题上,不信你自己来回答下试试?
equals和hashCode是object类的重要方法
如果重写了equals不一定但最好重写hashCode
言归正传,关于是否要同时重写equals和hashCode的问题,我的答案是: 如果重写了equals最好重写hashCode,这几乎是默认的规则。
因为Java对于没有重写equals和hashCode时的规定如下:
如果两个对象通过equals方法比较相等,则他们hashCode的返回值一定要相等。但如果两个对象的hashCode值相等,他们通过equals方法比较的返回值则不一定相等。
如果两个对象hashCode的返回值相等,不能判断两个对象是相等的。但如果两个对象的hashCode的返回值不相等,则可以判定两个对象一定不相等。
以上所说的规则可以简单归纳为:
-
两个对象相等,hashCode一定相等
-
两个对象不等,hashCode不一定不等
-
hashCode相等,两个对象不一定相等
-
hashCode不等,两个对象一定不等
可以说如果理解了这四句话,你就能明白equals和hashCode要不要同时重写的问题了。 看到这里,你完全明白了吗? 如果你刚要准备点头却又慢慢摇起头来,那么你可能就是面试被刷的那个人了,你还得接着往下看,下面是对以上总结的具体解释。
equals和hashCode是两个形影不离的好朋友,但彼此又不那么信任
也许对很多常写增删改查的小伙儿伴来说,这两个方法可能一个都没有重写过,更别说去琢磨是否要同时重写了呢? 所以,要想弄明白不同时重写equals和hashCode会发生怎样的后果,我们需要先整明白以下几点:
-
equals和hashCode有什么作用? 他们是什么关系?
-
为什么要重写equals和hashCode?
-
为什么重写了equals最好也重写hashCode?
-
如何重写equals和hashCode才正确?
前方高能预警,大家坐稳扶好,老司机要发车了~
01.equals和hashCode有什么作用?他们是什么关系?
要了解这两个方法的作用,咱们得往Java的祖坟上刨,那就得看看Object这个根类了,因为Object是这两个方法的最终发源地。
先来看equals方法的源码:
public boolean equals(Object obj) { return (this == obj); }
怎么样是不是很简单? 就是这么粗暴,一个==号就解决了。 很明显equals方法就是比较两个对象是否相等,通过其引用地址值来进行比较。
相比较equals方法,hashCode方法就没有那么简单了,其源码如下:
public native int hashCode();
它是一个native方法,可以根据平台自行实现,但它对其实现提出了一定的要求:
-
在同样的条件下,同一个对象无论运行多少次,返回的hash值必须一样。
-
如果两个对象通过equals方法比较判定相等,则他们通过hashCode方法返回的hash值也必须相等。
-
如果两个对象通过equals方法比较判定不相等,则不必保证他们通过hashCode返回的hash值不相等。
因此,这两个方法的作用就是为了对象间的比较,而他们之间的关系都和其方法的规则和约束有关,就像我们上文总结的规则一致,小伙伴们可以再返回上文回味一下,说不定会有新的领悟哦~
02.为什么要重写equals和hashCode?
因为这两个方法都跟对象的比较有关,所以如果在程序中要做对象比较,那大概率要重写这两个方法了。 因为equals默认的比较逻辑就是对象的地址进行比较,两个对象内存地址肯定不同,所以无论如何两个对象通过eqals比较肯定返回false。
但在实际编程中,我们经常会遇到去重,或者将对象放到有序集合中,或者将对象存入无重复的集合中,这时如果没有重写equals和hashCode,则无法达到需求。
举个例子,系统中同时存在两个对象,对象A和对象B,其姓名和身份证号一模一样。 此时,在系统内存中是两个对象,但其内容一致分明是一个人同时产生了两条重复信息。 如果使用默认的equals方法比较,则这两个对象永远不相等,永远不能比出来是一条相同的重复信息。 所以,要重写equals和hashCode方法来达到以上需求效果。
03.为什么重写了equals最好也重写hashCode?
这个问题其实上面的规则已经讲的很明白了,如果你能理解上面两者的约束关系,你基本不会有这个疑问。 但既然提出来了,我就再啰嗦两句。 接着上面的例子讲,如果有很多对象的信息要放到一个HashSet集合中,我们都知道HashSet有去重唯一的特点,此时,若让这些元素去一个个的equals比较,未免太损耗性能。
所以HashSet的实现引入了HashCode,先比较其HashCode值,如果相等再比较equals,这样就大大提高了效率。所以,如果你只重写了equals而没有重写hashCode,在使用集合时可能会出现意想不到的结果哦!
04.如何重写equals和hashCode才正确?
关于这个问题,你不但要理解上文的重写它们的原因,你必须要遵循好上文提到的规则和约束,否则就会出现你不想看到的状况结果。 此外,再总结下equals重写时必须遵守的规范特性,以确保重写的正确性:
-
自反性: x.equals(x)==true,自己永远equals自己
-
对称性: 如果x.equals(y)==true,那么y.equals(x)==true,相同的两个对象互相equals比较永远相等
-
一致性: 在x、y没有修改的情况下,多次比较x.equals(y)的结果一致
-
传递性: 如果x.equals(y)==true且y.equals(z)==true,则x.equals(z)==true
总结:以上就是对于equals和hashCode方法为什么要同时重写的经典Java面试题的解答,小伙伴儿们掌握了吗?如果有更多见解,欢迎留言讨论!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 为什么要同时重写 equals 和 HashCode?这个经典面试题你会答吗?
- 能用js重写的都会被typescript重写
- 重写equals的详细说明
- SpringSession:请求与响应重写
- 什么时候要重写equals
- 如何重写object虚方法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
分布式服务架构:原理、设计与实战
李艳鹏、杨彪 / 电子工业出版社 / 2017-8 / 89.00
《分布式服务架构:原理、设计与实战》全面介绍了分布式服务架构的原理与设计,并结合作者在实施微服务架构过程中的实践经验,总结了保障线上服务健康、可靠的最佳方案,是一本架构级、实战型的重量级著作。 《分布式服务架构:原理、设计与实战》以分布式服务架构的设计与实现为主线,由浅入深地介绍了分布式服务架构的方方面面,主要包括理论和实践两部分。理论上,首先介绍了服务架构的背景,以及从服务化架构到微服务架......一起来看看 《分布式服务架构:原理、设计与实战》 这本书的介绍吧!