Java通用列表<列表<?扩展号码>>
为什么在java中我们无法做到:
List<List<? extends Number>> aList = new ArrayList<List<Number>>();
尽管这没问题:
List<? extends Number> aList = new ArrayList<Number>();
编译器错误消息为:
Type mismatch: cannot convert from ArrayList<List<Number>> to List<List<? extends Number>>
# 1 楼答案
# 2 楼答案
在Java中,如果}的{}也不是{}的{}。我们说
Car
是Vehicle
的派生类,那么我们可以将所有Cars
视为Vehicles
;aCar
是aVehicle
然而,{List<Car>
与List<Vehicle>
不协变强>Java要求您显式地告诉它何时要使用协方差和逆变与通配符,由
?
标记表示。看看你的问题发生在哪里:内部
List<? extends Number>
工作是因为Number
确实扩展了Number
,所以它匹配“? extends Number
”。到目前为止,一切顺利。下一步是什么但是,组合的内部类型参数
List<? extends Number>
与List<Number>
不匹配;类型必须完全相同。另一个通配符将告诉Java,这种组合类型也应该是协变的:# 3 楼答案
您的语句未编译,因为
List<? extends Number>
与List<Number>
的类型不同。前者是后者的超类型你试过这个吗?在这里,我表示列表在其类型参数中是协变的,因此它将接受
List<? extends Number>
的任何子类型(包括List<Number>
)甚至这个。此处,右侧ArrayList的类型参数与左侧的类型参数相同,因此差异不是问题
你应该可以说
我倾向于尽可能避免使用
?
类型的通配符。我发现在类型注释中产生的费用不值得这样做# 4 楼答案
你一定要用这个?如果合适,请键入通配符,一般不要避免使用通配符。例如:
允许您传递
List<Integer>
或List<Long>
只允许传递声明为
List<Number>
的参数。一个小的区别,是的,但是使用通配符是强大且安全的。与看起来的相反,aList<Integer>
不是子类,或者不可从List<Number>
赋值。List<Integer>
也不是List<? extends Number
的子类,这就是上面的代码无法编译的原因# 5 楼答案
我不太熟悉Java语法,但您的问题似乎是:
Covariance & Contravariance