2013-01-09 106 views
19

我在閱讀泛型,並且我不明白需要使用未綁定的通配符以及它與原始類型的區別。我讀this question,但仍然沒有明白。在Java tutorial page for unbound wildcard我有以下兩點,我不明白第一點:未綁定通配符和原始類型之間的差異

  • 如果你正在寫,可以使用在Object類提供的功能來實現的方法。
  • 當代碼使用泛型類中不依賴於類型參數的方法時。例如,List.size()List.clear()。實際上,Class<?>經常使用,因爲Class<T>中的大多數方法不依賴於T

有人可以請解釋非結合通配符和外行語言的原始類型之間的區別。

List<?>List<Object>有什麼不同?

+1

請注意,術語「原始類型」是指對通用類型的非參數化引用,例如, '列表'與'列表'。略有不同的概念。 – Alex

+4

只需指出'List '不是原始類型,其泛型類型是'Object'。原始類型將是'List'。 – Dmitri

回答

33

如何List<?>List<Object>

的主要區別不同的是,第一行編譯,但第二個沒有:

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

然而,因爲你不知道什麼是通用List<?>的類型是,您不能使用其參數化方法:

List<?> list = new ArrayList<String>(); 
list.add("aString"); //does not compile - we don't know it is a List<String> 
list.clear(); //this is fine, does not depend on the generic parameter type 

至於與原始類型(無仿製藥),下面編譯代碼和區別運行良好:

List list = new ArrayList<String>(); 
list.add("aString"); 
list.add(10); 
+0

到目前爲止,但未綁定的原始類型有多不同,爲什麼我們需要unboud通配符?你可以用一些很好的例子來解釋它嗎? –

+0

@Sandy IMO的主要區別在於,使用未綁定的通配符(例如在方法簽名中)表示所討論的方法意識到泛型並承諾該對象的泛型類型。對於原始類型,所有投注都關閉 - 您可以將一個數字添加到字符串列表中,如圖所示 - 混合通用代碼和原始代碼可能導致ClassCastExceptions的風險。 – Alex

+0

@Sandy我說明了未綁定(第二個例子)和原始類型(第二個例子)之間的區別。什麼不清楚他們? – assylias

4

如何List<?>List<Object>不同?

List<Object> l1 = new ArrayList(); 
    List<?> l2 = new ArrayList(); 
    l1.add("Object"); 
    //l2.add("Object"); incorrect 
    l2.add(null); 

可以空值只增加了List<?>

2

就個人而言,我發現這個additional link from the Java tutorial on wildcards很有幫助。

一個我List<?>List之間看到的主要區別在於,前者永遠只能是有益的,從它的元件讀取(除非你真的想添加null),後者允許(未選中)將任意類型對象的它可能帶來意想不到的副作用。

0

例如,列表在方法簽名中用於調用從不需要類型參數的方法,即從列表讀取或旋轉它。

void someMethod(List<?> list) { 
    list.clear(); // I will never add anything to the list in here 
} 

你永遠不會添加任何東西,或以其他方式修改列表相對於它擁有你不能到列表中,除了空與此簽名的方法添加任何東西,因此你永遠不會打破類型安全的類型。原始列表另一方面,你可以做任何事情,因爲我們都知道可能導致類型違反安全。

void someMethod2(List list) { 
list.add(new WeaselFurBrush()); 
} 
List list1 = new ArrayList<String>(); 
someMethod2(list1);// oops 
相關問題