重写的超类Equals和HashCode,并认为我应该对Subclass做同样的事情

时间:2011-12-15 15:16:57

标签: java equals hashcode

我有一个包含2个变量(int a)(int b)的超类,并且有一个子类,它通过现在在子类中使用改进的方法覆盖2个超类方法来扩展超类的功能。作为我的子类的一部分,我现在有了一个新的intint c),它是一个唯一的ID(UUID)。

我理解使用equals方法

难以保持平等

我是否可以覆盖超类equalshashCode方法以显示相等性,并根据上述情况对子类equalshashCode方法执行相同的操作?

我最初覆盖了超类中的equalshashCode方法。如果它也应该为子类完成,因为子类中有额外的实例变量(int c)。我了解应该有一个hashCode方法来展示这一点,并且我读了haschCode是否已更改,那么子类的equals方法必须更改?

我真的很担心最好做什么。

我想知道我的超类equalshashCode方法是否可以显示平等关系?是否允许与我的超类equalshashCode覆盖方法一起使用,子类可以显示等于int aint bint c以及{{的比较1}}子类的方法已更新,以显示hashCode s intab的唯一哈希码?

我在考虑在超类c方法中比较我的int s ab,并更新这两个变量和equals s {的哈希码在int方法中{1}},ab,更新这3个变量的哈希码。只是超类中的c是唯一的吗?

非常感谢此处提出的任何建议,因为我认为忽略而不是处理子类equalsint c方法中的int c可能是否定的。

提前致谢

5 个答案:

答案 0 :(得分:1)

基本上,您有两种可能的选择:

  1. 完全忽略c。根据{{​​1}}和a定义超类的相等性,不要在子类中重写它。

  2. 始终将超类和子类的实例视为不相等。它允许您在超类(基于ba)和子类(基于bab)中以不同方式定义相等。

    请注意,在这种情况下覆盖子类中的cequals()是不够的 - 在实现超类的hashcode方法时还需要一个特殊的技巧,请参阅有关{{1}的部分内容} How to Write an Equality Method in Java中的方法。

答案 1 :(得分:1)

您的问题的关键在于您是否希望超类的实例和子类的实例比较相等。

如果是这样,请勿覆盖equals()hashCode()方法。您甚至可以在超类中创建它们final

如果没有,那么每个类的equals()方法应使用equals()检查getClass()的参数类型,而不是instanceof。例如,在超类中:

if ((obj == null) || (!getClass().equals(obj.getClass()))
  return false;
/* Compare a and b. */
...

在子类中:

if (!super.equals(obj))
  return false;
/* Compare c. */
...

如果哈希码基于ab字段,您可能不会拥有来覆盖hashCode()方法,但是您的课程如果您在子类的实现中考虑c,那么它可能会更好地作为键。也就是说,它会将具有不同值c的密钥放入不同的桶中,而不是在同一个散列桶中使用相同的ab聚集所有实例。

答案 2 :(得分:0)

++ to Jordan Bently。

对于您编写的每个班级,覆盖equals()toString()hashCode()通常是个好主意。在实践中,它并不总是有意义的。但是对于你正在做的事情,我会这样做。是的,您可以更改子类中的实现。

最好使用@Override标记每个覆盖方法,以帮助向您要覆盖的开发人员提供文档。这让他们知道你至少要覆盖java.lang.Object,如果不是你的超级班。

答案 3 :(得分:0)

这取决于。让我们说你的超级班级是AB extends A然后就可以发生

  • a.equals(a)
  • b.equals(b)
  • a.equals(b)(是)? b.hash == a.hash:hash无所谓
  • b.equals(a)(是)? b.hash == a.hash:hash无所谓

AB应该如何相关?有两种选择:

  1. AB完全不同,因此a.equals(b)b.equals(a) 始终为假。这是最<强>安全的方式。您需要等于测试a.getClass() == b.getClass();以确保ab 完全相同的类型。例如,Eclipse IDE默认在generate equals()和hashCode()中自动生成这种相等。
  2. 可以比较
  3. AB,但您无法在B中覆盖它以保持equals()hashCode().的合同这是强制到期的对称契约(a.equals(b) == b.equals(a))等于。

答案 4 :(得分:0)

为了确定hashCode和equals的行为,您需要考虑几种情况。

class Foo { int a, b; }
class Bar extends Foo { int c;}

具有相同a和b值的Foo和Bar是否相等(即,它们是否代表相同的值)?如果是这样,那么将equals和hashCode实现添加到Foo,并且不要在Bar中覆盖它。在equals中,确保检查对象是否为instanceOf Foo,而不是类是否相等。

具有不同c的Bar实例是否相等?如果是这样,那么不要覆盖Foo的hashCode和equals的实现。

否则,你应该在Foo和Bar中都有equals和hashCode的实现。确保设计它以使Foo实例仅等于其他Foo实例,并且Bar实例仅等于其他Bar实例。如果没有,你很容易违反equals所要求的对称性,例如

Foo x = new Foo(a,b);
Bar y = new Bar(a,b,c);
x.equals(y); //returns false
y.equals(x); //returns true

以上情况非常糟糕,如果您将Foo和Bar放入Set中,会导致奇怪的行为。

最后,你不应该为这些对象编写自己的hashCode实现和equals。大多数IDE都有自动生成工具,而不是使用它。