13

可能重复:
在 Java 中覆盖 equals 和 hashCode

如果我有

class A {
    int x = 1;
}
...
A a1 = new A();
A a2 = new A();
a1.equals(a2);

如果我比较 A 的 2 个实例而不覆盖 equals 方法,我会得到预期的结果吗?

4

3 回答 3

32

如果我比较 A 的 2 个实例而不覆盖 equals 方法,我会得到预期的结果吗?

这取决于你的期望:)

默认实现将为您提供引用相等性- 换句话说,当您比较两个引用时,equals只有当它们是对同一对象的引用时才会返回 true。

您通常会重写equals以实现“值相等”——两个不同的对象被视为相等,通常是因为它们本身具有相等的字段值。相等的确切含义将取决于您的设计 - 例如,这两个对象仍然可以通过其他方式区分。

如果您覆盖equals,您应该覆盖hashCode以与 一致equals,例如如果a.equals(b)为真,则a.hashCode() == b.hashCode()。这将允许您的类的实例用作基于哈希的集合(例如)中的键,以便您可以根据等于HashMap原始键的键查找值,而不必使用对确切的引用原始关键对象。

于 2012-10-30T06:55:19.003 回答
3

如果我比较 A 的 2 个实例而不覆盖 equals 方法,我会得到预期的结果吗?

不,因为您已经明确创建了两个不同的实例。

为什么?equals 的默认实现检查两个相关对象是否指向 java 虚拟内存中的相同内存位置(并且此默认行为在 java.lang.Object.equals() 中定义)

什么时候需要重写 equals 和 hashcode 方法?

程序员同时覆盖 equals() 和 hashcode() 的最常见情况是,如果您需要使用相关类的实例作为

  1. java.util.Map 实现中的键
  2. java.util.Set 实现中的值
  3. 您想检查同一类的两个不同实例之间的值是否相等(在这种情况下重写 equals() 是强制性的, hashcode() 不是 - 但这是一个很好的编程习惯)

equals 和 hashcode 的一般合约是:

if a1.equals(a2)
    it is mandatory that a1.hashcode() == a2.hashcode()
if a1.hashcode() == a2.hashcode()
    it is not mandatory that a1.equals(a2)

我想有足够的数据来处理一天:)

于 2012-10-30T07:09:18.260 回答
2

equals测试变量是否引用同一个对象的默认实现。如果这不是您想要的,那么您需要覆盖equals. 当您覆盖时,equals您通常需要覆盖hashcode该对象才能在哈希表(或其他使用哈希码的数据结构)中使用。

于 2012-10-30T06:55:30.187 回答