2011-12-30 90 views
2

我正在爲SCJP/OCPJP學習,並且遇到了一個接近我的奇怪問題。實例化類型的泛型類<?>

示例代碼實例化兩個通用的集合:

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

的「正確」答案的問題是,這個代碼將編譯,但加入要麼集合將產生一個運行時錯誤。

當我嘗試編譯這樣的代碼時,我只是得到錯誤。 Java教程甚至沒有顯示這種類型的代碼,它通常使用通配符作爲upcast的一部分。

Collection<?> c = new ArrayList<String>(); 

上面即使是合法的代碼,這兩個泛型集合?第二個由我的邏輯只會禁止接口。第一個看起來完全沒用。爲什麼要使用一種通用的方法來控制?

+0

看不到這會編譯和你可以添加到兩個集合就好 - 只是只有一個對象。我把它作爲練習讓讀者弄清楚每個班級哪個對象是有效的:) – Voo 2011-12-30 19:26:56

+0

你也不能這樣做。我想知道問題/答案是否是錯誤的,而且顯然是這樣。 – jeremyjjbrown 2011-12-30 20:18:25

+0

剛剛投票因爲什麼原因? – jeremyjjbrown 2014-03-01 18:52:26

回答

4

退房出色Java generics tutorial PDF。更具體地說有關通配符的部分包含回答你的問題,我引用

Collection<?> c = new ArrayList<String>(); 
c.add(new Object()); 

因爲我們不知道是什麼的c代表元素類型,我們不能 對象添加到它。 add()方法採用類型爲E的參數,集合的元素類型爲 。當實際類型參數是?, 它代表某種未知類型。我們通過添加的任何參數 都必須是此未知類型的子類型。由於我們不知道什麼樣的 類型,我們不能通過任何東西。唯一的例外是null, 這是每種類型的成員。

+0

該文件確實非常有用。謝謝!你是否知道任何反射或內心階層都很好的文章? – jeremyjjbrown 2011-12-31 03:44:47

1

我在this的答案中回答了這個問題。 ?不能用於實例化。我不確定它爲什麼說代碼會編譯,我用過的任何java編譯器都不允許這樣做。你可以做什麼是由以下如上圖所示:

List<?> list = new ArrayList(); 

這將編譯和運行,但你不能這樣做:

list.add("hello world"); //This wouldn't compile 
2

如果要聲明在運行時類型,你可以做這樣的事情:

public class Clazz1<T> { 

private final List<T> list = new ArrayList<T>(); 

private List<T> getList() { 
    return list; 
} 

/** 
* @param args 
*/ 
public static void main(String[] args) { 
    Clazz1<Integer> clazzInt = new Clazz1<Integer>(); 
    clazzInt.getList().add(2); 
    System.out.println(clazzInt.getList()); 

    Clazz1<String> clazzString = new Clazz1<String>(); 
    clazzString.getList().add("test"); 
    System.out.println(clazzString.getList()); 
} 

} 
0

new生產對象的具體實例。具體實例只能有一種類型,包括任何泛型。知道這一點,通配符不能與new一起使用。