Java中A<B<? extends Integer>>赋值给A<B<?>>为何编译通过?
class A<T> { } class B<T extends Integer> { } public class Main { public static void main(String[] args) { A<B<?>> a1 = null; A<B<? extends Integer>> a2 = null; a1 = a2; } }
问题
我认为在此程序中,a1的类型并非a2类型的超类型,且捕获转换对两者的类型均为恒等转换。我认为a1 = a2;属于转换链,根据JLS 5.2规定:
若转换链中包含两个无父子类型关系(§4.10)的参数化类型,会触发编译错误。
但编译器未报错或警告,为何该赋值操作被允许?
解答
这是因为B<?>和B<? extends Integer>在当前场景下本质是等价类型,进而A<B<?>>和A<B<? extends Integer>>具备合法的子类型关系,符合赋值转换规则。
具体来说,泛型类B的类型参数被声明为T extends Integer,这意味着B的所有参数化类型,其类型参数的上限都被固定为Integer。此时B<?>中的通配符?会被隐式限定为? extends Integer——通配符无法突破类定义时设定的类型参数上限。因此B<?>和B<? extends Integer>是完全等价的参数化类型,它们的捕获转换结果也一致:都会生成以新类型变量(上限为Integer)为参数的B类型。
对于泛型类A<T>,既然B<? extends Integer>与B<?>等价,那么A<B<? extends Integer>>可被视为A<B<?>>的子类型(甚至可认为两者本质是同一类型),因此a1 = a2的赋值操作完全符合JLS规则,不会触发编译错误。
内容的提问来源于stack exchange,提问作者user24723440
相关产品推荐
相关产品推荐

