java 中的通配符和类型参数范围

Wildcard and type pameter bounds in java

考虑这个案例:

class A {}

class B<T extends A, E extends T> {
    B<?, A> b;
    B<?, ? extends A> b2;
}

据我了解,在这种情况下,TE 的有效上限都是 class A。所以问题是:为什么 javac 在字段 b 的声明中不接受 class A 作为参数,但在字段 b2 的声明中接受 wildcard ? extends A

您的声明不正确。您错过了 'wildcard'-s 的要点。它们用于未知的 属性 声明。对于 B<?, E> b E 必须扩展 TT 必须扩展 A 但是你说第一个通用类型是 ?未知!所以你说一个未知的参数必须扩展 T 所以 A。这是不正确的。

您创建的关系类似于 E -> T -> A。之后,您声明为 1. 泛型类型 ? -> E -> T -> A 和 2. 泛型类型 A -> E -> T -> ?。所以 ?必须延长?并且 A 必须扩展 E vs.. 这对于编译器来说是令人困惑和未知的...

与以下类:

class A {}
class C extends A {}
class B<T extends A, E extends T> {}

可以这样想:

E extends T extends A
使用 B<?,A> 然后 T -> ?E -> A
A extends ? extends A
? 可以是 A 的任何子类,比方说 C.
A extends C extends A显然无效。
所以这就是编译错误的原因。


Eclipse 用户注意事项:

Eclipse 4.9.0 编译器不支持 javac 8u 和 Intellij,并且没有针对 B<?,A> 中的通用参数发出编译错误。我假设这是 Eclipse 编译器中的错误,但我没有咨询 JLS 来确认这一点。

class B<T extends A, E extends T> {
    B<?, A> b; // <-- Eclipse does NOT emit a compile error
    B<?, ? extends A> b2;
}

已报告此假定错误 here

在字段 b 的声明中,类型 T 可以是扩展 A 的任何内容。反过来 E 必须扩展 T,但是您为 T 提供类型 AA 不会是 A.

子类的子类