Java - 基类和子类中的 equals 方法

标签 java equals

我有一个简单的基类,后来由许多单独的类扩展,这些类可能会引入新的字段,但不一定。我在基类中定义了一个 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/

相关文章:

java - Wiremock 记录 — 在记录模式下重写响应 'on the fly'

java - 将文本文件中的大矩阵加载到 Java 数组中

Java:调用 hashCode() 和 equals() 时自动抛出 UnsupportedOperationException 的干净方法?

java - 重写等于方法

java - setAdapter 导致应用程序崩溃

java - Realm 对象不是此 Realm 架构的一部分

java - 安卓;在运行时获取 "the application has stopped unexpectedly"

c# - ((System.Object)p == null)

java - 编辑文本等于

java - 为什么 assertEquals(new Object[] {"abc"}, new Object[] {"abc"});不失败?