2015-01-13 107 views
0

我有一個問題來獲取列表的類型。問題是聲明我沒有指定類型。我只在運行時設置它。泛型 - 獲取引用類型

我有一個POJO類

public class MyObject<T> { 

    private String name; 
    private List<T> list; 

//getter and setter 
} 

我按照this SO question,並試圖我下面的代碼

public class ListType { 

    public static void main(String[] args) throws NoSuchFieldException, SecurityException { 
     ListType listType = new ListType(); 
    List<Integer> listInt = new ArrayList<Integer>(); 
    MyObject<Integer> myObjectInt = new MyObject<Integer>(); 
    myObjectInt.setList(listInt); 
    listType.initialize(myObjectInt); 

    MyObject<String> myObjectStr = new MyObject<String>(); 
    List<String> listStr = new ArrayList<String>(); 
    myObjectStr.setList(listStr); 
    listType.initialize(myObjectStr); 
    } 

    private void initialize(MyObject myObject) throws NoSuchFieldException, SecurityException { 
     List list = myObject.getList(); 
     ListType listType = new ListType(); 
     listType.getListType(list); 
    } 

    private void getListType(List list) throws NoSuchFieldException, SecurityException { 
     Field stringListField = MyObject.class.getDeclaredField("list"); 
     ParameterizedType stringListType = (ParameterizedType) stringListField.getGenericType(); 
     Class<?> stringListClass = (Class<?>) stringListType.getActualTypeArguments()[0]; 
     System.out.println(stringListClass); 
    } 

} 

然後我得到以下異常

Exception in thread "main" java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class 
    at com.sample.listtype.ListType.getListType(ListType.java:35) 
    at com.sample.listtype.ListType.initialize(ListType.java:27) 
    at com.sample.listtype.ListType.main(ListType.java:15) 

如何獲得類型如果我在運行時設置?

+2

*但是,如何獲取類型,如果我設置在運行時?* List在運行時沒有類型([erasure](http://docs.oracle.com/javase/tutorial/java/generics/erasure.html)),所以這個問題並沒有什麼意義。最好告訴我們你真正想要做什麼。 – Radiodef

回答

2

我不認爲你想達到什麼是可能的。然而,對代碼稍加改動就做的伎倆:

public class MyObject { 
    private List<?> list; 
    private Class<?> type; 

    public <T> void setList(List<T> list, Class<T> c) { 
     this.list = list; 
     this.type = c; 
    } 

    public List<?> getList() { 
     return list; 
    } 

    public Class<?> getType() { 
     return type; 
    } 
} 

示例代碼:

public static void main(String[] args) throws NoSuchFieldException, 
     SecurityException { 
    List<Integer> list = new ArrayList<Integer>(); 
    MyObject myObject = new MyObject(); 
    myObject.setList(list, Integer.class); 

    System.out.println(myObject.getType()); 
} 

輸出:

class java.lang.Integer 
+2

也許使整個'MyObject'類泛型也是OP的一個選項。由於類型擦除,它不會避免額外的參數,但會引入更多的類型安全性。 –

+0

嗨,我編輯了代碼。請檢查。無論如何,現在我怎麼能得到這種類型? – iCode

+0

@AndreStannek確實使MyObject成爲泛型類會更安全,但是可以將列表設置爲任何類型。即MyObject 不能設置Double的任何列表,我想這個功能對於這個問題是必要的。 –

1

方法getGenericType()具有返回類型Type,其中可以是ClassParameterizedType。如果在沒有參數化類型的字段上調用它,則不會返回ParameterizedType。在這種情況下,它似乎返回Classjavadoc對這個有點不確定。

至於你如何在運行時獲取實際類型的問題:泛型類型信息在運行時被擦除。它僅用於確保編譯時的類型安全。如果將實際類型爲ArrayList<Integer>的對象分配給靜態類型爲List的變量,則無法在運行時獲取實際對象的通用類型。你可以做的是檢查列表中包含的對象的類型:

Class<?> foo = list.get(0).getClass(); 
+2

這是一個很好的解決方法,但當列表中沒有任何元素時,它將不起作用... –

+0

是的,如果列表爲空,該怎麼辦? – iCode

+1

@NielsBillen是的,在這種情況下,它不會工作;-)我喜歡你的答案,我不得不做一次類似的事情。 –