1

I've been trying to get a clear understanding of what the end of the follwing code outputs:

class C {

public int foo(C p) { return 1; }

}

class D extends C {

public int foo(C p) { return 2; }
public int foo(D p) { return 3; }

}

C p = new C();
C q = new D();
D r = new D();

int i = p.foo(r);
int j = q.foo(q);
int k = q.foo(r);

Ultimately, after scouring many forums, I have come to the general understanding of why i = 1, j = 2, and k = 2, but I'm still not entirely clear on why k = 2, mostly because I've gotten different explanations that end up with the same result.

To my understanding, q is statically of type C, so at compile time, the best match is foo(C p) in C, but it is overridden by D's foo(C p) at runtime. So because it originally was the best match and r just so happens to extend C, D's foo(C p) is used rather than D's foo(D p). Is my understanding of this correct?

3

Yes, your understanding of this is correct.

At runtime, as far as the JVM is concerned, overloading doesn't exist, because the compiler made sure all methods have different names (actually, different descriptors). This is essentially what the JVM sees:

class C {
    public int foo_taking_C_returning_int(C p) { return 1; }
}

class D extends C {
    // overrides the method in C
    public int foo_taking_C_returning_int(C p) { return 2; }
    // doesn't override anything because there's no matching method in C
    public int foo_taking_D_returning_int(D p) { return 3; }
}

C p = new C();
C q = new D();
D r = new D();

int i = p.foo_taking_C_returning_int(r);
int j = q.foo_taking_C_returning_int(q);
int k = q.foo_taking_C_returning_int(r);
1
  • Oh wow, a light bulb went off in my head just with the help of your comments in the code. Thanks alot!!
    – TacoB0t
    Oct 18 '16 at 1:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.