2014-01-06 81 views
4

如何創建一個具有指定類型參數的列表? 例如:Java - 創建對象擴展列表

LinkedList<Integer> list = createList(LinkedList.class, Integer.class); 

我試着爲它創造一個方法,但在創建新實例時方法不包括類型參數。

public static <T, L extends List<T>> L createList(Class<L> listClazz, Class<T> valueClazz) throws Exception 
{ 
    return listClazz.getConstructor().newInstance(); 

    //Instead of 
    // new L<T>(); 
    //does 
    // new L(); 
} 

我希望我的問題很清楚,謝謝你的幫助。

+1

您正在將運行時編譯時間與運行時混合在一起,泛型沒有任何關係,爲什麼要使用反射? – nachokk

+1

你可以谷歌的「Java類型擦除」。 –

回答

8

你不能那樣做。泛型在運行時沒有業務,因此您無法在運行時使用反射創建參數化實例。在運行時,LinkedList<Intege>只是一個LinkedList。類型信息 - Integer在編譯時通過「類型擦除」擦除。關鍵是,你爲什麼想這樣做?

+0

如果是這樣,我怎樣才能得到一個列表的類型參數? 我正在考慮製作一個像這樣的方法: fillList(new LinkedList ()); 但我必須從列表中獲得'Integer'類。 – Limeth

+1

@Limeth再次,你不能在運行時獲取類型信息。但是對於這種情況,有使用反射的解決方法。 –

+0

我做了一個存儲類,它擴展了HashMap ,基本上允許從YAML和MySQL加載數據。我會使用該方法來反序列化存儲在MySQL單元格中的序列化列表。 – Limeth

1
//Instead of 
// new L<T>(); 
//does 
// new L(); 

兩個 「做」 完全是一回事。你怎麼知道它是「做」而不是其他?類型參數是編譯時錯覺,用於類型檢查。它們與代碼「做什麼」無關。要創建一個LinkedList<T>的實例,您不需要知道T是什麼,因爲它在類型擦除後並不存在。

我認爲你遇到的問題與函數內部的代碼無關,而是與方法的簽名無關。由於該方法是按原樣聲明的,並且您正在向其傳遞Class<LinkedList>(的類型LinkedList.class)的表達式,所以L必須是LinkedList,並且由於此方法返回L,因此編譯器必須考慮將其返回按類型LinkedList。這與這個方法中的代碼沒有任何關係。

如果您想將方法的返回類型視爲LinkedList<Integer>,那麼只需傳入Class<LinkedList<Integer>>類型的表達式即可。很簡單,對吧?如何獲得Class<LinkedList<Integer>>類型的表達式?首先,你可以做(Class<LinkedList<Integer>>)(Class<?>)LinkedList.class

如果這看起來有點虛假,這是因爲Class從根本上說是一個運行時的東西 - 它允許運行時創建該類中的對象。將它與Generics一起使用,這是一種編譯時類型檢查機制,從根本上說是有缺陷的。對於任何類,只有一個類對象存在,例如, LinkedList。是LinkedList還是LinkedList<Integer>LinkedList<String>?那麼,它可能是所有這些,從某種意義上說,newInstance()方法可以創建它們中的任何一個(在運行時沒有區別)。

+0

你介意舉個例子嗎?聽起來很有希望。 – Limeth