1

Given the following class

public class Test<T extends Test.UpperClass> {

    public static class BottomClass {}
    public static class UpperClass extends BottomClass {}
    public void method(BottomClass c) {
        System.out.println("BottomClass " + c.getClass());
    }
    public void method(T c) {
        System.out.println("UpperClass " + c.getClass());
    }
    public void test() {
        method(new UpperClass());
    }
    public static void main(String[] args) {
        new Test<UpperClass>().method(new UpperClass()); // calls method(T)
        new Test<UpperClass>().test(); // calls method(BottomClass)
    }
}

The code above if executed, will print out UpperClass class Test$UpperClass and BottomClass class Test$UpperClass, which is not what I expected as T extends UpperClass, I would expect both will call method(T) as the erasure of T is UpperClass. Why method(BottomClass) is called instead?

1
  • You can't pass a UpperClass where T is expected. Why would the erasure matter? Commented Nov 22, 2017 at 4:18

1 Answer 1

2

Let's simplify:

public class Foo<T> {
    void method(T t) {}

    void test() {
        method(new Object());  // compiler error: is T Object?
    }

    public static void main(String[] args) {
        new Foo<Object>().test();
        new Foo<String>().test(); // both must compile!
    }
}

The above method call doesn't compile, because the instance can't know what type T is. The fact that Object and T have the same erasure is irrelevant at compile time. Your example is a more convoluted demonstration of the same.

Sign up to request clarification or add additional context in comments.

22 Comments

Thanks. But if erasure does not matter, then in your example code, why can't you add void method(Object t) {}?
@user1589188 The compiler needs to make sure the methods can be distinguished at runtime, so it can't allow signatures with the same erasure. That's one of the unfortunate failings of generics in Java. But if type erasure took full effect at compile time, generics wouldn't exist at all.
Thats the reason of my question: if method(T) has the same signature as method(Object) after erasure and is not allowed, then why calling method(new Object()) does not call method(T)? I know it won't compile, but I am after the logical reason behind.
@user1589188 Because the signature affects overload resolution, which also happen at compile time.
Yes you answered why having both method(T) and method(Object) is not allowed. My question is about given method(T) and method(Object) are having the same signature after erasure, then why calling method(new Object()) does not call method(T)?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.