我有一个简单的基类,后来由许多单独的类扩展,这些类可能会引入新的字段,但不一定。我在基类中定义了一个 equals 方法,但也为一些子类覆盖了它。可以在基类/子类中混合定义吗?在我的例子中,这是为了避免检查相同字段的代码重复。
最佳答案
看看"Implementing equals() To Allow Mixed-Type Comparison"来自 Angelika Langer。
以下是一些问题的简要说明和可能的解决方案:
平等契约说(除其他外):
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
这意味着如果您的子类正在引入新字段并且您正在将基类(或不覆盖 equals 的另一个子类)的对象与该子类的对象进行比较,您可能会遇到问题。
请勿执行以下操作:
class BaseClass {
private int field1 = 0;
@Override
public boolean equals(Object obj) {
if (obj instanceof BaseClass) {
return field1 == ((BaseClass) obj).field1;
}
return false;
}
}
class BadSubClass extends BaseClass {
private int field2 = 0;
@Override
public boolean equals(Object obj) {
if (obj instanceof BadSubClass) {
return super.equals(obj)
&& field2 == ((BadSubClass) obj).field2;
}
return false;
}
}
因为你得到
BaseClass baseClass = new BaseClass();
BadSubClass subClass = new BadSubClass();
System.out.println(baseClass.equals(subClass)); // prints 'true'
System.out.println(subClass.equals(baseClass)); // prints 'false'
可能的解决方案:
用类比较替换instanceof
检查:
obj != null && obj.getClass() == getClass()
使用此解决方案,BaseClass
的对象永远不会等于任何子类的对象。
如果您创建另一个 SubClass
而没有 equals
方法的 @Override
,则两个 SubClass
对象可以开箱即用地彼此相等(如果 BaseClass.equals
检查决定如此),但是 SubClass
对象永远不会等于 BaseClass
-对象。
一个好的实现可能如下:
class BaseClass {
private int field1 = 0;
@Override
public boolean equals(Object obj) {
if (obj != null && obj.getClass() == getClass()) {
return field1 == ((BaseClass) obj).field1;
}
return false;
}
}
class GoodSubClass extends BaseClass {
private int field2 = 0;
@Override
public boolean equals(Object obj) {
if (obj instanceof GoodSubClass) {
return super.equals(obj) && field2 == ((GoodSubClass) obj).field2;
}
return false;
}
}
请引用上面提到的文章,了解更高级的问题及其解决方案。
关于Java - 基类和子类中的 equals 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13162188/