2014-09-05 131 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對象。