繁体   English   中英

Java通用列表<List <?扩展数>>

[英]Java Generic List<List<? extends Number>>

为什么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>>

在Java中,如果Car是派生类Vehicle ,那么我们可以将所有Cars视为Vehicles ; Car是一种Vehicle 但是, Cars List也不是Vehicles List 我们说List<Car>不是 List<Vehicle>

Java要求您明确告诉它何时使用协方差和逆向通配符,由?表示? 令牌。 看看你的问题发生在哪里:

List<List<? extends Number>> l = new ArrayList<List<Number>>();
//        ----------------                          ------
// 
// "? extends Number" matched by "Number". Success!

内部List<? extends Number> List<? extends Number> works,因为Number确实扩展了Number ,所以它匹配“ ? extends Number ”。 到现在为止还挺好。 下一步是什么?

List<List<? extends Number>> l = new ArrayList<List<Number>>();
//   ----------------------                    ------------
// 
// "List<? extends Number>" not matched by "List<Number>". These are
//   different types and covariance is not specified with a wildcard.
//   Failure.

但是,组合内部类型参数List<? extends Number> List<? extends Number>List<Number>不匹配; 类型必须完全相同 另一个通配符将告诉Java这个组​​合类型也应该是协变的:

List<? extends List<? extends Number>> l = new ArrayList<List<Number>>();

我对Java语法不是很熟悉,但似乎你的问题是:

协方差和反演

你一定要用? 在适当的时候键入通配符,不要将其作为一般规则来避免。 例如:

public void doThingWithList(List<List<? extends Number>> list);

允许您传递List<Integer>List<Long>

public void doThingWithList(List<List<Number>> list);

允许您只传递声明为List<Number> 一个小的区别,是的,但使用通配符是强大而安全的 与它看起来相反, List<Integer>不是List<Number>的子类,也不是可分配的。 List<Integer>也不是List<? extends Number的子类List<? extends Number List<? extends Number ,这就是上面代码无法编译的原因。

你的语句没有编译,因为List<? extends Number> List<? extends Number>List<Number>类型不同。 前者是后者的超类型。

你试过这个吗? 这里我表示List在其类型参数中是协变的,因此它将接受List<? extends Number>任何子类型List<? extends Number> List<? extends Number> (包括List<Number> )。

List<? extends List<? extends Number>> aList = new ArrayList<List<Number>>();

甚至这个。 这里右侧的ArrayList的类型参数与左侧的类型参数相同,因此方差不是问题。

List<List<? extends Number>> aList = new ArrayList<List<? extends Number>>();

你应该可以说

List<List<Number>> aList = new ArrayList<List<Number>>();

我倾向于避免? 尽可能输入通配符。 我发现类型注释中产生的费用不值得。

List<List<? extends Number>> aList = new ArrayList<List<? extends Number>>();
aList.add(new ArrayList<Integer>());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM