跳過編譯器,獲取泛型參數的實際類型
import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Vector; public class GenericTest { public static void main(String[] args) throws Exception { //泛型類型是給編譯器看的,編譯成class字節碼文件後會丟棄類型信息,所以通過反射是無法知道泛型所存儲的實際類型的 List<String> list = new ArrayList<String>(); list.add("java"); //collection.add(20); //編譯報錯,因為編譯期間嚴格檢查泛型的實際數據類型 //由上結論可知,既然編譯成class文件後不會保存類型信息,那麼是不是就可以通過反射的方式存儲任意類型的數據呢? //示例:通過反射在collection中存儲除String以外的數據 list.getClass().getMethod("add", Object.class).invoke(list,5); list.getClass().getMethod("add", Object.class).invoke(list, new Date()); System.out.println(list.size()); //結果是3 //用下麵的方式去獲取元素會報ClassCaseException,因為List中第1和第2條記錄都不是String類型,所以取出來的時候會報類型轉換異常 //System.out.println(list.get(1)); //說明:上麵示例隻想說明,JAVA中的泛型是提供給編譯器檢查使用的,可以限定集合中的輸入類型,讓編譯器擋住源程序中的非法輸入,編譯器編譯帶類型說明的集合時會丟棄“類型”信息,使用程序運行效率不受影響 //由於無法在運行期間獲取某個帶類型的集合屬性的實際類型,但可以獲得方法參數列表中泛型參數的實際類型 Method method = GenericTest.class.getMethod("getGenericActualType", List.class,Vector.class); Type[] types = method.getGenericParameterTypes(); for(int i = 0; i < types.length; i++) { ParameterizedType pt = (ParameterizedType) types[i]; System.out.print("泛型原始類型: " + pt.getRawType() + "\t"); System.out.println("泛型實際類型: " + pt.getActualTypeArguments()[0]); } } /* * 獲得泛型參數的原始類型,示例方法 */ public static void getGenericActualType(List<Date> list,Vector<String> vector) { } }
通過反編譯工具獲取GenericTest.class的源代碼:
最後更新:2017-04-02 22:16:21