Java两级泛型奇怪的行为

Java两级泛型奇怪的行为,java,generics,type-parameter,Java,Generics,Type Parameter,我有以下逻辑 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> { Te

我有以下逻辑


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不应该知道Gentest的实际类吗?

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

当编译器编译Gen时,它对E一无所知,也就是说,它不能保证E扩展了A,因此它必须用调用test重载

如果删除该测试重载,将出现编译错误,因为另一个测试根本不兼容: 类型测试中testE扩展A的方法不适用于参数E


要使其调用另一个,请更改为Gen.

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

当编译器编译Gen时,它对E一无所知,也就是说,它不能保证E扩展了A,因此它必须用调用test重载

如果删除该测试重载,将出现编译错误,因为另一个测试根本不兼容: 类型测试中testE扩展A的方法不适用于参数E


要让它调用另一个,请更改为Gen.

这不是很明显吗?当您通过mnew B代时会发生什么。让我知道调用了哪个方法。在public void me e{test.teste;}e来自类Gen,但在那一点上它是未知的,所以编译器必须选择方法签名,它将匹配可以分配给e的任何类型,这里是public void teste{..}而不是public void teste{..}。如果您想让编译器知道E可能只接受A的子类,这样它就可以由public void testE处理。E{..}将它声明为类Gen{..}。对于Gen.mnew B,它返回的结果是相同的。这不是很明显吗?当您通过mnew B代时会发生什么。让我知道调用了哪个方法。在public void me e{test.teste;}e来自类Gen,但在那一点上它是未知的,所以编译器必须选择方法签名,它将匹配可以分配给e的任何类型,这里是public void teste{..}而不是public void teste{..}。如果您想让编译器知道,E可能只接受A的子类,这样它就可以由public void testE处理。E{..}将它声明为类Gen{..}。对于Gen.mnew B,它将返回相同的结果