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

时间:2018-12-28 13:37:54

标签: java bounded-wildcard unbounded-wildcard

考虑这种情况:

class A {}

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

据我了解类型边界,在这种情况下,TE的有效上限均为class A。那么问题来了:为什么javac在字段b的声明中不接受A类作为参数,而在字段wildcard的声明中接受? extends A b2

3 个答案:

答案 0 :(得分:1)

您的声明不正确。您错过了“通配符”的含义。它们用于未知属性声明。对于B<?, E> bE必须扩展T,而T必须扩展A,但是您说的第一个通用类型是?未知!因此,您说过,未知参数必须扩展T,依此类推A。不正确

您创建的关系就像E -> T -> A。之后,您声明为1.泛型类型? -> E -> T -> A和2.泛型为A -> E -> T -> ?。那呢必须延伸?和A必须扩展E与。对编译器而言,这是令人困惑且未知的...

答案 1 :(得分:1)

具有以下类别:

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报告了此假定的错误。

答案 2 :(得分:0)

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