2014-11-02 57 views
4

因此,Google提出了很多關於獲取參數化類型.class的問題,但我試圖以另一種方式。如何使用Class對象作爲參數化類型?

我有一個類的列表,我需要製作一個地圖,它使用Class作爲鍵和一個類型爲Class的對象的ArrayList作爲值。就像這樣:

Class[] classes = getArrayOfClasses(); 
HashMap<Class, ArrayList<?>> map = new HashMap<Class, ArrayList<?>>(); 
for(Class c : classes) { 
    map.put(c, new ArrayList<c>()); // here is where the problem is 
} 

問題當然是它需要一個參數化類型,而不是一個類。一種可能的解決方法是隻使用map.put(c, new ArrayList<Object>()),但是我必須知道類型並投射每個物體。

MyClass myObj = (MyClass) map.get(MyClass.class).get(0); 

我也試圖使一個初始化函數是這樣的:

private <T> ArrayList<T> makeArrayList(Class<T> c) { 
    return new ArrayList<T>(); 
} 

這不得不說我希望將工作的語法,但它仍然給我留下的ObjectArrayList是不得不投。

那麼有什麼辦法可以讓ArrayList參數化爲類的類型?

+0

使用通用方法:'列表 getList(類別類型)'。 – 2014-11-02 19:51:07

回答

2

不幸的是,由於Java泛型的性質(它們通過擦除工作),泛型在運行時不可用。

這意味着沒有真正的方法來使map.put(c, new ArrayList<c>());工作。

我建議不要做這樣的:裹在一個專門的對象列表,並給該對象的下列訪問方法:

public <T> getList(Class<T> key) { 
    List<?> list = map.get(key); 
    return (List<T>) list; 
} 

這將產生一個警告,但只要在地圖構建好吧,你會沒事的。

或者,您可以對所有對象執行運行時檢查,以確保類型匹配。

public <T> getList(Class<T> key) { 
    List<?> list = map.get(key); 
    for(Object o : list){ 
     assert(key.isInstance(o)); 
    } 
    return (List<T>) list; 
} 
+0

我希望有一種方式來解決類型擦除類型是一個類,但我猜不是。在一個函數中包裝演員並抑制警告可能是最好的解決方法。謝謝 – 2014-11-02 21:14:35

1

是絕對在編譯的字節代碼之間沒有差異:

new ArrayList(); 
new ArrayList<T>(); 
new ArrayList<String>(); 
new ArrayList<Integer>(); 

類型參數對經編譯的代碼沒有影響;它隻影響編譯器的類型檢查。所以,如果類型參數在編譯時不可用,那麼它是沒用的,因爲編譯時是唯一有用的時間。

您應該只寫new ArrayList<Object>()new ArrayList<Integer>()甚至new ArrayList<CompletelyBogusUnrelatedClass>();這並不重要,因爲它們都與ArrayList<?>兼容,這是您的地圖的值類型。

至於你的方法,創建並返回一個ArrayList,它應該只是這樣寫:

private static <T> ArrayList<T> makeArrayList() { 
    return new ArrayList<T>(); 
} 

(這是正確的,這個方法返回的任何元素類型你想要ArrayList甚至不知道什麼這種類型是!這是一個清楚的演示,在運行時不需要類型參數。)

相關問題