Java通用列表<List <? 扩展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中,如果CarVehicle的派生类,那么我们可以把所有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>工作,因为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. 

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

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

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

协变与逆变

你一定要用这个? 在适当的时候input通配符,一般不要回避。 例如:

 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<Number>不是同一个types。 前者是后者的超types。

你尝试过吗? 在这里,我表示List在types参数中是协变的,所以它将接受List<? extends Number>任何子typesList<? extends Number> List<? extends Number> (其中包括List<Number> )。

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

甚至这个。 这里右边的ArrayList的types参数和左边的types参数是一样的,所以方差不是问题。

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

你应该可以说

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

我倾向于避免? 尽可能地input通配符。 我发现types注释中的花费是不值得的。

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