Java 二级泛型的奇怪行为

Java two level generics strange behaviour

我有以下逻辑


public class Why {

    public static void main(String[] args) {
        Gen<A> gen = new Gen<>();
        gen.m(new A()); //eeeeeeeeee A
    }
}

class A {}

class B extends A {}

class C extends A {}

class Gen<E> {
    Test test = new Test();

    public void m(E e) {
        test.test(e);
    }
}

class Test {

    public <E extends A> void test(E e) {
        System.out.println("XXXXXXXXXX " + e.getClass().getSimpleName());
    }

    public <E> void test(E e) {
        System.out.println("eeeeeeeeee " + e.getClass().getSimpleName());
    }

}

main 的输出意味着编译器在测试中选择了第二个方法,这很奇怪还是我错过了什么? java 不应该知道 Gen#test 的实际 class 吗?

方法重载解析发生在编译时。

当编译器编译Gen<E>时,它对E一无所知,即它不能保证E扩展A,所以它必须用 <E>.

调用 test 的重载

如果删除 test() 的重载,则会出现编译错误,因为另一个根本不兼容:
The method test(E extends A) in the type Test is not applicable for the arguments (E)

要使其调用另一个,请更改为 Gen<E extends A>