2012-01-01 249 views
4

爲什麼編譯器問題的變量聲明爲編譯器警告

時警告
List<? extends Object> list = new LinkedList(); 

警告:

Note: ZiggyTest.java uses unchecked or unsafe operations. 
Note: Recompile with -Xlint:unchecked for details. 

但是,當我變量聲明爲

它不發出警告
List<?> list = new LinkedList(); 
+0

結帳http://stackoverflow.com/questions/8683137/and-extends-object/8683314和我的答案中的優秀泛型教程那裏是一個必須閱讀時使用泛型 – Robin 2012-01-01 21:48:01

+0

它不發佈任何減少正如你在NetBeans 6.9.1中用jdk 6所提到的那樣。 – Lion 2012-01-01 22:01:47

+0

我沒有使用IDE。從命令行提示編譯時,是否會收到警告? – ziggy 2012-01-01 22:15:33

回答

1

我無法解釋爲什麼編譯器不會將這些視爲等價的,但假定它不這樣做,我會試着解釋它爲什麼拒絕這麼做。

第一個(List<? extends Object>)聲稱List中保存的對象的類型是來自Object的某種未知類型。第二個(List<?>)說少;它只是說列表中的對象的類型是未知的。它沒有提及任何預期的超類型作爲未知類型的上界。

爲了驗證第一個假設,編譯器希望聽到您說出在此處構造的List實例中保留的預期類型,作爲原始類型LinkedList,該主題沒有提到任何內容。但是,如果要將實例構造爲LinkedList<Object>類型,則至少要保證對實例的協變讀取與您的斷言保持一致:即,此列表中的內容是某種Object

現在,這一切似乎都傻了,因爲Java中的每個參考/非原始類型擴展Object,所以不應該在List<? extends Object>List<?>之間的理解上發生歧義;畢竟,第二個意味着第一個意義上的,因爲語言的類型系統的授權單根分類階層。

2

這出現在Java 5和更高版本,如果您使用的集合沒有類型說明符(例如Arraylist()而不是ArrayList<String>())。這意味着編譯器無法使用generics以類型安全的方式檢查您是否正在使用該集合。

要擺脫警告,只需具體說明要在集合中存儲什麼類型的對象。所以,與其

List list = new ArrayList(); 

應儘可能

List<String> list = new ArrayList<String>(); 

在你的情況,如果你修改聲明如下,

List<? extends Object> list = new LinkedList<Object>(); 

將與任何警告,因爲編譯我們現在使用通用類型(<Object>)來使其類型安全。

+0

'新的LinkedList <?擴展對象>();'不編譯 – Robin 2012-01-01 21:50:47

+0

除了你不能在聲明中使用通配符.. – Voo 2012-01-01 21:51:19