cast on object of type superclass returns object of type subclass in java

I have implemented the following code in order to understand the difference between static and dynamic binding:

class A {

    int met(A a) {
        return 0;
    }

    int met(B b) {
        return 1;
    }

    int met(C c) {
        return 2;
    }
}

class B extends A {

    int met(A a) {
        return 3;
    }

    int met(B b) {
        return 4;
    }

    int met(C c) {
        return 5;
    }
}

class C extends B {

    int f() {
        return ((A)this).met((A)this);
    }
}

public class Test {

    public static void main(String[] args) {

        C x = new C();
        System.out.println(x.f());
    }
}

The result I get is 3, but I don't understand why, since the first cast is made to A.

Jon Skeet
people
quotationmark

So, let's look at the call:

((A)this).met((A)this);

That's equivalent to:

A target = this;
A argument = this;
target.met(argument);

So, for the last line, the compiler looks up the signature based on the compile-time types involved - it will look in A (and superclasses) for a method called met which has a parameter that is compatible with A (the compile-time type of the argument). Overload resolution finds that the answer is:

int met(A a)

That's determined the signature at compile-time. However, the implementation of that method is determined at execution time, based on the execution-time target of the method call. That type is C here - because this is a reference to an instance of C. (The f method is called on an instance of C.)

Now C doesn't override int met(A a), but B (its superclass) does - so that's the implementation that's used. It doesn't matter that B also overrides met(B b) and met(C c) because the compiler has already determined that it's the met(A a) method which is being called.

people

See more on this question at Stackoverflow