不兼容的类型:List of List 和 ArrayList of ArrayList。

52

以下行代码导致错误:

Incompatible Types.

List<List<Integer>> output = new ArrayList<ArrayList<Integer>>();

原因是什么?

编辑

我知道如果将我的第二个ArrayList更改为List,它就不会出错。不过,我想知道错误的原因。谢谢。


ArrayList<ArrayList<Integer>> output = new ArrayList<ArrayList<Integer>>(); 是有效的。 - Mustafa sabir
7个回答

36

正确的写法应该是: List<List<Integer>> ret = new ArrayList<List<Integer>>(); 这样,您可以将不仅 ArrayList,还包括 LinkedList 添加到 ret 中。


35
如果你有一个 List<List<Integer>>,那么你可以向其中添加一个 LinkedList<Integer>。但是对于一个 ArrayList<ArrayList<Integer>>,你无法这样做,因此后者不可能是 List<List<Integer>> 的一种类型。

34

来自泛型、继承和子类型

这是在使用泛型编程时的一个常见误解,但学习这个概念是很重要的。

enter image description here

Box<Integer>并不是Box的子类型,即使Integer是Number的子类型。


2
这并没有回答问题。问题是“原因是什么?”你所做的只是重新陈述问题的前提,使用不同的类。 - Dawood ibn Kareem

13
原因是泛型不支持协变。
考虑一个简单的情况:
List<Integer> integers = new ArrayList<Integer>();
List<Number> numbers = integers; // cannot do this
numbers.add(new Float(1337.44));

现在List持有一个浮点数,这显然很糟糕。 你的情况也是如此。
List<ArrayList<Integer>> al = new ArrayList<ArrayList<Integer>>();
List<List<Integer>> ll = al; // cannot do this
ll.add(new LinkedList<Integer>())

现在你有一个名为ll的列表,它保存了LinkedList,但是al声明为ArrayList列表。


3
没有变异的语言在多态方面会更加有趣。 - dfeuer

7

Java Doc中明确指出:

一般来说,如果Foo是Bar的子类型(子类或子接口),并且G是某个泛型类型声明,则不是这种情况:G<Foo>G<Bar>的子类型。这可能是你需要学习有关泛型的最困难的事情,因为它违反了我们根深蒂固的直觉。

同样的情况也发生在这里,即Bar = List<Integer>Foo = ArrayList<Integer>,因为ArrayList<ArrayList<Integer>>不是List<List<Integer>>的子类型。


5

更少的文字,更多的修复:

List<List<Integer>> lists = new ArrayList<>();

或者

List<List<Integer>> lists = new ArrayList<List<Integer>>();

问题是“原因是什么”。 - Dawood ibn Kareem

0

在使用泛型之前,您应该了解两个原则。

1. 泛型参数应该相同:

LinkedList<String> res = new LinkedList<String>();

2. 参数应该直接继承自Object类,如Integer,Character和List或Array。(LinkedList是List的子类,因此不能是泛型的参数)

这里有一个正确的演示:

LinkedList<List<Integer>> res = new LinkedList<List<Integer>>(); 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接