我有一个包含2个变量(int a
)(int b
)的超类,并且有一个子类,它通过现在在子类中使用改进的方法覆盖2个超类方法来扩展超类的功能。作为我的子类的一部分,我现在有了一个新的int
(int c
),它是一个唯一的ID(UUID)。
我理解使用equals
方法
我是否可以覆盖超类equals
和hashCode
方法以显示相等性,并根据上述情况对子类equals
和hashCode
方法执行相同的操作?
我最初覆盖了超类中的equals
和hashCode
方法。如果它也应该为子类完成,因为子类中有额外的实例变量(int c
)。我了解应该有一个hashCode
方法来展示这一点,并且我读了haschCode
是否已更改,那么子类的equals
方法必须更改?
我真的很担心最好做什么。
我想知道我的超类equals
和hashCode
方法是否可以显示平等关系?是否允许与我的超类equals
和hashCode
覆盖方法一起使用,子类可以显示等于int a
,int b
和int c
以及{{的比较1}}子类的方法已更新,以显示hashCode
s int
,a
和b
的唯一哈希码?
我在考虑在超类c
方法中比较我的int
s a
和b
,并更新这两个变量和equals
s {的哈希码在int
方法中{1}},a
和b
,更新这3个变量的哈希码。只是超类中的c
是唯一的吗?
非常感谢此处提出的任何建议,因为我认为忽略而不是处理子类equals
和int c
方法中的int c
可能是否定的。
提前致谢
答案 0 :(得分:1)
基本上,您有两种可能的选择:
完全忽略c
。根据{{1}}和a
定义超类的相等性,不要在子类中重写它。
始终将超类和子类的实例视为不相等。它允许您在超类(基于b
和a
)和子类(基于b
,a
和b
)中以不同方式定义相等。
请注意,在这种情况下覆盖子类中的c
和equals()
是不够的 - 在实现超类的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. */
...
如果哈希码基于a
和b
字段,您可能不会拥有来覆盖hashCode()
方法,但是您的课程如果您在子类的实现中考虑c
,那么它可能会更好地作为键。也就是说,它会将具有不同值c
的密钥放入不同的桶中,而不是在同一个散列桶中使用相同的a
和b
聚集所有实例。
答案 2 :(得分:0)
++ to Jordan Bently。
对于您编写的每个班级,覆盖equals()
,toString()
和hashCode()
通常是个好主意。在实践中,它并不总是有意义的。但是对于你正在做的事情,我会这样做。是的,您可以更改子类中的实现。
最好使用@Override
标记每个覆盖方法,以帮助向您要覆盖的开发人员提供文档。这让他们知道你至少要覆盖java.lang.Object
,如果不是你的超级班。
答案 3 :(得分:0)
这取决于。让我们说你的超级班级是A
和B extends A
然后就可以发生
a.equals(a)
b.equals(b)
a.equals(b)
(是)? b.hash == a.hash:hash无所谓b.equals(a)
(是)? b.hash == a.hash:hash无所谓 A
和B
应该如何相关?有两种选择:
A
和B
完全不同,因此a.equals(b)
或b.equals(a)
始终为假。这是最<强>安全的方式。您需要等于测试a.getClass() == b.getClass();
以确保a
和b
完全相同的类型。例如,Eclipse IDE默认在generate equals()和hashCode()中自动生成这种相等。A
和B
,但您无法在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都有自动生成工具,而不是使用它。