Search code examples
javadowncastupcasting

Why upcasted ab.a + ab.b produce result 1 and 1.0?


I don't get how we managed to invoke constructor without parameters in class A at all. How upcasting works in this particular example? When we produce A ab = bb; what exactly ab refers to?

public class A {
    public Integer a;
    public Float b;

    public A() {
        a = 1;
        b = 1.0f;
    }

    public A(Integer x) {
        a = 2;
        b = 2.0f;
    }

    public int f(long x) {
        return 3;
    }

    public int f(double x) {
        return 4;
    }

}
public class B extends A {
    public int a;

    public B(float x) {
        a = 5;
    }

    public int f(int x) {
        return 6;
    }

    public int f(float x) {
        return 7;
    }

    public int f(double x) {
        return 8;
    }

}
public class M {
    public static void main(String[] args) {
        A aa = new A(1);
        System.out.println(aa.a + " " + aa.b);// OUT: [ 2 ] [2.0]

        int ret = aa.f(aa.b);
        System.out.println(ret); // OUT: [ 4 ]

        B bb = new B(6);
        A ab = bb;
        System.out.println(bb.a); // OUT: [ 5 ]
        System.out.println(ab.a + " " + ab.b);// OUT: [ 1 ] [1.0]

        ret = bb.f(1);
        System.out.println(ret); // OUT: [ 6 ]

        ret = ab.f(1.0f);
        System.out.println(ret); // OUT: [ 8 ]

        ret = ab.f(aa.a);
        System.out.println(ret); // OUT: [ 3 ]

        ret = bb.f(aa.b);
        System.out.println(ret); // OUT: [ 7 ]

    }
}

Solution

  • When we produce A ab = bb; what exactly ab refers to?

    It references bb, but as an A, i.e. one can only call methods and attributes defined in A. There is no new object constructed. You can see this by checking System.out.println(bb == ab);, which will evaluate as true. This concept is known as attribute- or field-hiding.

    This also is the reason why ab.a returns 1, because the attribute a (of type Integer) within A is accessed. If one would, on the other hand, access bb.a, one would get the attribute a (ob type int) within B, which is initialzed to be 5. Keep in mind that, if you construct a B, there is always an explicit or implicit call to a superclass constructor as defined in JLS, §12.5.