在下面的代碼導致編譯時間錯誤:(?捕獲#1-的擴展對象)泛型和參數化類型中的Java
的方法中的添加型 List是不適用於 參數(字符串)
代碼:
List<? extends Object> a1 = new ArrayList();
a1.add("string");
錯誤是在線:
a1.add("string");
由於class String從Object繼承而來,爲什麼ref a1不接受String類型?
在下面的代碼導致編譯時間錯誤:(?捕獲#1-的擴展對象)泛型和參數化類型中的Java
的方法中的添加型 List是不適用於 參數(字符串)
代碼:
List<? extends Object> a1 = new ArrayList();
a1.add("string");
錯誤是在線:
a1.add("string");
由於class String從Object繼承而來,爲什麼ref a1不接受String類型?
我建議你閱讀這篇文章,http://java.dzone.com/articles/covariance-and-contravariance。 (斜體添加是我的)
綜上所述,我們使用的協方差
<? extends Object>
當我們只打算採取通用 值出的結構。我們用逆變<? super Object>
當我們只打算 把通用值放入結構,我們用一個不變<Object>
當我們 打算一舉兩得。
您已定義列表,拿着協變的對象類型,這意味着你可以寫Object o = a1.get(1)
,但你不能寫a1.add("foo")
。如果您希望能夠添加對象,但不是讓他們回來,那麼你就需要這樣定義列表:
List<? super Object> a1 = new ArrayList<>();
這有點不幸,在我看來,語言的作者使用的術語extend
和super
以表示協變和逆變,特別是在上面的例子中,因爲沒有超類型Object
。
? extends Object
的意思是「一些未知類型X
,延伸Object
」。通過嘗試將String
添加到集合中,您基本上聲稱編譯器無法驗證X = String
。據編譯器知道,X
也可以是Integer
或完全不同的東西。
換句話說List<? extends Object>
並不意味着「任何延伸Object
去」。簡單的List<Object>
意味着。
List<? extends Object>
可用於每種類型的列表。
你怎麼想,那會是安全的,讓它添加任何對象,如果例如
List<? extends Object> a1 = new ArrayList<Integer>();
a1.add("string");
只能在安全值增加會null
因爲它不屬於任何特定的類型。
爲了擺脫這個問題,你可以使用例如List<String> a1 = new ArrayList<String>()
或List a1 = new ArrayList()