双重装箱通配符返回类型出现意外额外通配符的原因探究
为什么Codec的decode方法返回类型是Box>而非预期的Box<Box<?>>?
核心原因:通配符捕获与泛型不变性
当你使用Codec<?>时,编译器会将这个通配符捕获为一个具体但未知的类型(标记为capture#1-of ?)。也就是说,Codec<?>在编译时等价于Codec<C>,其中C是某个确定但编译器无法知晓的类型。此时decode()方法的返回类型就变成了Box<Box<C>>,而非你预期的Box<Box<?>>。
为什么直接赋值给Box<Box<?>>会报错?
Java泛型默认是不变的:即使Box<C>是Box<?>的子类型,外层的Box<Box<C>>和Box<Box<?>>之间也不存在继承关系。编译器不允许这种直接赋值,因为会破坏类型安全——比如你可以通过Box<Box<?>>将Box<Integer>放入原本应该存放Box<String>的容器,取出时会触发类型转换异常。
为什么Box>可以正常接收?
Box<Box<C>>是Box<? extends Box<?>>的合法子类型:
Box<C>本身是Box<?>的子类型(因为通配符?可以匹配任何类型,Box<C>可以向上转型为Box<?>)? extends Box<?>表示“某个Box<?>的子类型”,而Box<C>正好符合这个条件
因此编译器允许将Box<Box<C>>赋值给Box<? extends Box<?>>,这是利用上界通配符兼容子类型关系的合法方式。
结合代码示例拆解
- SimpleDecode方法:
Codec<T>中的T是确定的类型参数,decode()返回Box<Box<T>>,直接赋值完全匹配,编译通过。 - ExpectedWildCardDecode方法:
Codec<?>的decode()返回Box<Box<capture#1-of ?>>,它和Box<Box<?>>没有继承关系,因此触发类型不匹配错误。 - ObservedWildcardDecode方法:
Box<? extends Box<?>>通过上界通配符兼容了Box<Box<capture#1-of ?>>的子类型关系,所以编译正常。
内容的提问来源于stack exchange,提问作者Estecka
相关产品推荐
相关产品推荐

