2014-09-25 51 views
0

我曾問過類似的問題,這是在得到一個明確的答案,希望更具體的版本。 「?」 雖然試圖瞭解java泛型類型和外卡的使用,我試過如下:瞭解在java泛型中使用通配符?

List<Integer> li4 = new ArrayList<Integer>(); 
    li4.add(new Integer(5)); 
    Integer myInt4 = li4.get(0); 

現在我更換了更通用型「

List<? extends Integer> li = new ArrayList<Integer>(); 
Integer myInt = li.get(0); 

以上編譯罰款。 似乎上述被處理作爲一個列表,其中每個元素是一個整數「禮」(看li.get(0)調用)。 我也可以做到以下幾點:

li = li4; 

以上編譯運行正常。 但當我嘗試:

li.add(new Integer(5)); 

我獲得以下編譯錯誤(使用Oracle JDeveloper作爲IDE):

Error(24,9): cannot find method add(java.lang.Integer) 

「?擴展Integer'應該允許擴展Integer的任何類型。它的行爲與'get'方法相同,它返回一個Integer。同樣,它不會在ArrayList分配給它時發生抱怨。因此,例如'li = new ArrayList<String>()'不能編譯。那麼,爲什麼我允許指定另一個ArrayList<Integer>(),得到一個整數回去,但不能添加整數?

回答

5

? extends Integer確實不是表示「應允許任何擴展Integer的類型」。這意味着,這對於一些特定T擴展整數List<T>

所以你從List<? extends Integer>中得到的任何東西都會延伸Integer,但是你不能只是放入任何東西 - 我們不知道你放入的類型匹配T

爲了給出一個具體的例子,Integer延伸Number。所以,你可以寫

List<? extends Number> list1 = new ArrayList<Integer>(); 
List<? extends Number> list2 = new ArrayList<Double>(); 

但你不應該被允許寫list2.add(new MyNumber()),或list2.add(new Integer(3)),因爲list2實際上是一個List<Double>

+0

您提到「對於擴展Integer的某些特定T」。如果該特定的T擴展整數比'T'至少必須具有整數中找到的行爲。 – 2014-09-25 19:58:42

+1

這是真的,但它可能有更多的行爲。所以,如果你嘗試在列表中添加_just_一個簡單的'Integer'?擴展Integer>',它可能不具有它應該具有的所有行爲。 – 2014-09-25 21:19:49

0

下面的代碼讓我瞭解到了答案:

List<Exception> exL = new ArrayList<Exception>(); 
    exL.add(new Exception()); 
    Exception ex = exL.get(0); 
    Throwable th = exL.get(0); 
    exL.add(new NullPointerException()); 
    /** Error(153,7): cannot find method add(java.lang.Exception) 
    exL.add(new Throwable()); 
    **/ 

所以,當我們宣佈名單時,元素必須至少有異常的行爲,這意味着異常,RuntimeException的和它的子類。可以將從這樣的列表返回的元素分配給Exception或其任何子類。 「Exception e = exL.get(0)」或「Throwable th = exL.get(0)」。也可以添加一個Exception的實例,或者將NullPointerException聲明爲List。

列表genExcepList,可以是List,List或List,因爲「?extends Exception」表示Exception及其所有子類。實際上,List是List,List等的超類。對於這些列表類型中的任何一個,來自'get'調用的返回元素都保證爲Exception類型。所以可以這樣做:Exception e = genExcepList.get(0)。但是調用genExcepList並不好。添加(例外),因爲List必須滿足它允許哪些是List,List,List等每種類型的限制。唯一有效的是genExcepList.add(null),因爲'null'適用於每種類型。另一方面,如果我們有類似的東西: List rtgs = new ArrayList(); 「超級異常」表示異常及其超類。所以List代表List,List和List。在任何這些列表類型中,可以調用「add(new Exception());」所以可以調用rtgs.add(新的Exception())作爲Exception也是Throwable和Object。但是,從List返回的元素可以是Exception,Throwable和Object中的任何一個,因此調用「Exception ex = rtgs.get(0)」是不正確的。所以唯一可以安全工作的是「Object ex = rtgs.get(0)」。