深度解读 Java 中的 equals()、==、hashCode()

JAVA herman 56浏览

一般我们重写 equal() 时也会重写 hashCode(),而且 equal() 也经常被拿来和 == 做比较,所以我今天把它们三者放一起来说!

写这篇文章的主要原因是我在做 code review 的时候,发现有同学在错误的使用 HashSet,所以在写 HashSet 之前顺便先来说说 equals()、==、hashCode()。

quals()、==、hashCode()

equals()

equals() 的作用是用来判断两个对象是否相等。它定义在 JDK 的 Object 类中。源码如下:

public boolean equals(Object obj) {
    return (this == obj);
}

Object 类中的 equals() 方法默认是通过判断两个对象的地址是否相等(即,是否是同一个对象)来区分它们是否相等的。

由于 Object 类是所有类基类,所以所有的 Java 类都有 equals() 方法。只不过默认的 equals() 方法,等价于 ==。

因此,我们通常会重写 equals() 方法。若某个类没有覆盖 equals() 方法,当通过它的 equals() 比较两个对象时,实际上是比较两个对象是不是同一个对象。这时,等价于通过“==”去比较这两个对象。当我们覆盖了类的 equals() 方法后,通过 equals() 方法比较两个对象是否相等。比较的是两个对象的内容相等,若相等则 equals() 方法返回 true;否则返回 fasle。

Java 的 equals() 有 5 大特性:

  • 对称性:如果x.equals(y)返回是"true",那么y.equals(x)也应该返回是"true"。
  • 反射性:x.equals(x)必须返回是"true"。
  • 类推性:如果x.equals(y)返回是"true",而且y.equals(z)返回是"true",那么z.equals(x)也应该返回是"true"。
  • 一致性:如果x.equals(y)返回是"true",只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是"true"。
  • 非空性:x.equals(null),永远返回是"false";x.equals(和 x 不同类型的对象)永远返回是"false"。

所以,我们在重写 equals() 方法的时候,一定要检验检验是否达到了上面的 5 大特性。这 5 大特性也被称为 equals() 的 5 大重写规则。

==

== 的作用是判断两个对象的地址是不是相等。即,判断两个对象是不试同一个对象。

面试的时候,基本上都会问到 equals 方法与‘==’运算符有什么区别?如果你回答的是:“equals 比较的是对象的内容,而‘==’比较的是对象的地址”。那么这个答案严格来说是错误的,至少是不完全正确吧。

通过前面的内容我们知道 equals 方法在 Object 中的实现也是直接的使用了‘==’运算符进行比较的。所以回答这个问题一定要严谨,加上前置条件。

hashCode()

hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个 int 整数。一般在 hash 集合中会用到。hashCode() 统一定义在 JDK 的 Object 中,这就意味着 Java 中的任何类都包含有 hashCode() 函数。

那么为什么重写 equals() 的同时还得重写 hashCode() 呢?就是因为 HashMap,Hashtable,HashSet 等集合在处理键对象的哈希码来计算存储位置的时,并不能保证 hash 不冲突。另外在 equals() 方法相等的时候,hashCode() 也不一定相等。

但是在使用散列表时,我们要求如果两个对象的 equals() 相等,那么它们的 hashCode() 的话, 值一定相同。如果两个对象 hashCode() 相等,它们的 equals() 并不一定相等。

因为在散列表中,hashCode() 相等,即两个键值对的哈希值相等。然而哈希值相等,并不一定能得出键值对相等。补充说一句:“两个不同的键值对,哈希值相等”,这就是哈希冲突。

我们知道 HashSet 是一个不允许存储重复元素的集合,但是如果你没有重写元素类的 equals() 和 hashCode() 的话,HashSet 基本上就失去了意义。这也是为什么很多同学误用 HashSet,但并没有用出自己想要的结果的原因。

关于 HashSet 的内容,我后面会单独来讲。有问题请关注我的微信公众号,给我留言!

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加QQ1群:135430763(2000人群已满),QQ2群:454796847,QQ3群:187424846。QQ群进群密码:xttblog,想加微信群的朋友,可以微信搜索:xmtxtt,备注:“xttblog”,添加助理微信拉你进群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作可添加助理微信进行沟通!

本文原文出处:业余草: » 深度解读 Java 中的 equals()、==、hashCode()