[英]Java Generic type : difference between List <? extends Number> and List <T extends Number>
[英]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.