这要从 Object 类开始说起,我们知道 Object 类是 Java 的超类,每个类都直接或者间接的继承了 Object 类,在 Object 中提供了 8 个基本的方法,equals 方法和 hashcode 方法就是其中的两个。
equals 方法:Object 类中的 equals 方法用于检测一个对象是否等于另一个对象,在 Object 类中,这个方法将判断两个对象是否具有相同的引用,如果两个对象具有相同的引用,它们一定是相等的。
hashcode 方法:用来获取散列码,散列码是由对象导出的一个整数值,散列码是没有规律的,如果 x 和 y 是两个不同的对象,那么 x.hashCode() 与 y.hashCode() 基本上不会相同
为什么要重写 equals 和 hashcode 方法?为什么需要重写 equals 方法和 hashcode 方法,我想主要是基于以下两点来考虑:
1、我们已经知道了 Object 中的 equals 方法是用来判断两个对象的引用是否相同,但是有时候我们并不需要判断两个对象的引用是否相等,我们只需要两个对象的某个特定状态是否相等。比如对于两篇文章来说,我只要判断两篇文章的链接是否相同,如果链接相同,那么它们就是同一篇文章,我并不需要去比较其它属性或者引用地址是否相同。
2、在某些业务场景下,我们需要使用自定义类作为哈希表的键,这时候我们就需要重写,因为如果不做特定修改的话,每个对象产生的 hashcode 基本上不可能相同,而 hashcode 决定了该元素在哈希表中的位置,equals 决定了判断逻辑,所以特殊情况下就需要重写这两个方法,才能符合我们的要求。
我们使用一个小 Demo 来模拟一下特殊场景,让我们更好的理解为什么需要重写 equals 和 hashcode 方法,我们的场景是:我们有很多篇文章,我需要判断文章是否已经存在 Set 中,两篇文章相同的条件是访问路径相同。
好了,我们一起动手写 Demo 吧,我们建立一个文章类来存放文章信息,文章类具体设计如下:
class Article{ // 文章路径 String url; // 文章标题 String title; public Article(String url ,String title){ this.url = url; this.title = title; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }文章类中有路径、标题两个属性,在这个类中我们并没有重写 equals 和 hashcode 方法,所以这里会使用超类 Object 中的 equals 和 hashcode 方法,为了防止你没有看过 Object 类中的 equals 和 hashcode 方法,我们先一起来看一下 Object 的类中的 equals 和 hashcode 方法:
看完之后,接下来,我们编写一个测试类,测试类代码如下:
public class EqualsAndHashcode { public static void main(String[] args) { Article article = new Article("www.baidu.com","百度一下"); Article article1 = new Article("www.baidu.com","坑B百度"); Set<Article> set = new HashSet<>(); set.add(article); System.out.println(set.contains(article1)); } }在测试类中,我们实例化了两个文章对象,文章对象的 url 都是一样的,标题不一样,我们将 article 对象存入到 Set 中,判断 article1 对象是否存在 Set 中,按照我们的假设,两篇文章的 Url 相同,则两篇文章就应该是同一篇文章,所以这里应该给我们返回 True,我们运行 Main 方法。得到结果如下:
我们看到了结果不是你想要的 True 而是 False ,这个原因很简单,因为两篇文章的访问路径相同就是同一篇文章,这是我们定义的规则,我们并没有告诉我们的程序这个规则,我们没有重写 equals 和 hashcode 方法,所以系统在判断的时候使用的是 Object 类默认的 equals 和 hashcode 方法,默认的 equals 方法判断的是两个对象的引用地址是否相同,这里肯定是不一样的,得到的答案就是 False 。我们需要把相等的规则告诉我们的程序,那我们就把 equals 方法重写了。 1、重写 equals 方法
在这里我们先使用 IDEA 工具生成的 equals 方法,把最后的逻辑返回逻辑修改一下就好了,具体的编写规则我们下面会介绍。最后我们的 equals 方法如下
/** * 重写equals方法,只要两篇文章的url相同就是同一篇文章 * @param o * @return */ @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Article article = (Article) o; return Objects.equals(url, article.url); }