2014-07-04 210 views
1

考虑下面的类:覆盖equals方法不会被调用

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)。

这是为什么?

回答

10

你打电话b1.equals(b3) - b1Base一个实例,而不是Sub,所以没有办法你压倒一切的方法可以被调用。

哎呀,甚至b3.equals(b1)不会叫上Sub任何东西,因为b3Base实例为好。

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

+0

谢谢!我现在明白了.. – AngryOliver

2

让我们来看看你的代码(在main方法)运行

Base b1 = new Base(1);: - 创建新的基地(1)对象和引用b1。让我们把这个对象称为第一个对象。

Base b2 = b1;: - 创建基本类型的参考变量并分配b1变量的值,因此,无论b1和b2是指相同的对象(第一对象)

Base b3 = b2.foo();: - 创建基本类型的参考变量b3.foo()方法在第一基对象被调用,它返回一个新的基本对象(第二对象),其中这是我的属性值=第一对象的I属性值

Base b4 = new Sub(1);: - 创建新的子(1)对象和参考是b4。让我们把这个对象称为第三个对象。

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

b1.equals(b3): - 现在您已调用b1指示的对象的equals方法。 b1是指Base类型对象(第一个对象)。运行Base对象的equals方法。它有默认的equals方法。 (重写的方法在Sub对象中,这不是一个Sub Object。)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)); 
相关问题