overridden equals method doesn't get called

Consider the following classes:

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));
    }
}

The printed result is false. I've noticed the overridden method equals(Object o) never get caught and I suspect of course that this is the problem (Otherwise it would have printed true).

Why is that?

Jon Skeet
people
quotationmark

You're calling b1.equals(b3) - b1 is an instance of Base, not of Sub, so there's no way your overriding method can be called.

Heck, even b3.equals(b1) won't call anything on Sub, as b3 refers to an instance of Base as well.

Only b4 and b5 refer to instances of Sub, so only b4.equals(...) or b5.equals(...) will call your overridden method. Additionally, because you're unconditionally casting within your equals method, b4.equals(b1) (for example) will throw an exception rather than returning false.

people

See more on this question at Stackoverflow