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;
}
据我了解,在这种情况下,T
和 E
的有效上限都是 class A
。所以问题是:为什么 javac 在字段 b
的声明中不接受 class A 作为参数,但在字段 b2
的声明中接受 wildcard
? extends A
?
您的声明不正确。您错过了 'wildcard'-s 的要点。它们用于未知的 属性 声明。对于 B<?, E> b
E
必须扩展 T
而 T
必须扩展 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
提供类型 A
。 A
不会是 A
.
子类的子类
考虑这个案例:
class A {}
class B<T extends A, E extends T> {
B<?, A> b;
B<?, ? extends A> b2;
}
据我了解,在这种情况下,T
和 E
的有效上限都是 class A
。所以问题是:为什么 javac 在字段 b
的声明中不接受 class A 作为参数,但在字段 b2
的声明中接受 wildcard
? extends A
?
您的声明不正确。您错过了 'wildcard'-s 的要点。它们用于未知的 属性 声明。对于 B<?, E> b
E
必须扩展 T
而 T
必须扩展 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
提供类型 A
。 A
不会是 A
.