2014-09-05 121 views
5

不兼容类型错误导致我不明白的原因。泛型不兼容类型

为什么这段代码错了?

List<List<String>> a = new ArrayList<>(); 
List b = a; // is ok 
List<List> c = a; // incompatible types 

回答

7

它被描述为here。 Supertype兼容性仅适用于'外部'级别,但不适用于跨类型参数的'内部'。这不是直观的,但它是如何工作的... 此外,List是一种原始类型,它的行为与List<Object>略有不同 - 描述为here

3
List<List> 

隐含

List<List<Object>>

这不是

List<List<String>> 

为什么它成功的第一种情况是因为类型推断的原因父。 编译器将基本上检查需要哪种类型的表达,使感,它会产生

List<List<String>> a = b; 

在第二种情况下,将默认为

List<List<Object>> a = b // which does not compile 
+0

我明白了,但为什么第二行没有给出编译时错误,因为它会导致与第三行相同的运行时错误? – 2014-09-05 13:59:14

+0

这就是为什么你应该更喜欢泛型对原始类型的原因。在这种情况下,通用代码保证您的类型安全,原始代码不会。 – Seb 2014-09-05 14:05:14

3

写入

List b = a; 

不涉及泛型。它定义了一个名为b的原始List类型,它可以接受任何对象作为它的元素。

不要将其与

List<List> c = a; 

,因为它涉及仿制药比较,这就是为什么编译器将强制类型兼容性检查这里。

+0

是的,但如果进一步在代码中,我们将调用b.add(new Object());它会抛出运行时错误,因为我们基本上会做a.add(new Object()); 我现在的问题是为什么第三行通过在编译时给出错误来防止意外错误,而第二行不会造成 – 2014-09-05 14:02:08

+0

这个运行时错误与我们对类型兼容性检查的缺陷没有关系。 – 2014-09-05 14:04:31

+0

我认为你的评论已经在我的回答中得到了解答。 – 2014-09-05 14:10:12

2

简短回答:因为您的c列表包含一个包含所有类型对象的列表。
例如,您也可以添加Integer对象。
a列表只能包含String对象。