重写的equals方法不会被调用

时间:2014-07-04 10:54:26

标签: java oop inheritance override

考虑以下课程:

public class Base {

    protected int i = 0;

    public Base(int i) {
        this.i = i;
    }

    public Base(Base b) {
        this(b.i);
    }

    public Base foo() {
        return new Base(this);
    }
}


public class Sub extends Base {

    public Sub(int i) {
        super(i);
    }

    public Sub(Sub s) {
        super(s.i * 2);
    }

    public Base foo() {
        return this;
    }

    @Override
    public boolean equals(Object o) {
        return ((Sub) o).i == this.i;
    }

    public static void main(String[] args) {
        Base b1 = new Base(1);
        Base b2 = b1;
        Base b3 = b2.foo();
        Base b4 = new Sub(1);
        Base b5 = b4.foo();

        System.out.println(b1.equals(b3));
    }
}

打印结果为false。我注意到被覆盖的方法equals(Object o)永远不会被抓住,我当然怀疑这是问题(否则它会打印true)。

为什么?

2 个答案:

答案 0 :(得分:10)

您正在呼叫b1.equals(b3) - b1Base的实例,而不是Sub的实例,因此无法调用您的覆盖方法。

哎呀,即使b3.equals(b1)也不会在Sub上调用任何内容,因为b3也会引用Base的实例。

b4b5引用Sub的实例,因此 b4.equals(...)b5.equals(...)会调用您的重写方法。此外,由于您在equals方法中无条件投射,b4.equals(b1)(例如)会抛出异常,而不是返回false

答案 1 :(得分:2)

让我们看看您的代码(在主方法中)如何运行

Base b1 = new Base(1);: - 创建新的Base(1)对象,引用为b1。让我们将此Object称为第一个对象。

Base b2 = b1;: - 创建一个Base类型引用变量并赋值b1变量,所以b1和b2都指向同一个对象(第一个对象)

Base b3 = b2.foo();: - 在第一个Base对象中创建一个Base类型引用变量b3. foo()方法,它返回一个新的Base对象(第二个对象),在那里它' si属性值=第一个对象>属性值

Base b4 = new Sub(1);: - 创建新的Sub(1)对象,引用为b4。让我们将此Object称为第三个对象。

Base b5 = b4.foo();: - 在第三个对象(Sub)中创建一个Base类型引用变量b5. foo()方法,并将其自己的引用作为Base类型返回。 Sub可以将自己的引用作为Base返回,因为Base是它的超类。

b1.equals(b3): - 现在你调用了b1引用的对象的equals方法。 b1指的是Base类型对象(第一个对象)。运行Base对象的equals方法。它具有默认的equals方法。 (重写方法位于Sub对象中,而不是Sub对象。)default equals方法检查其哈希码是否相同。 b1是第一个对象,b3是第三个对象。所以b1和b3不相等。

因此输出应为false

这里没有任何压倒性的事情发生。

如果您按如下方式更改了代码,则可以覆盖输出

Base b1 = new Sub(1);
Base b3 = b1.foo();
Base b4 = new Sub(1);
Base b5 = b4.foo();

System.out.println(b4.equals(b3));