閱讀452 返回首頁    go 阿裏雲 go 技術社區[雲棲]


跳過編譯器,獲取泛型參數的實際類型

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

  上一篇:go jQuery中的toggle方法
  下一篇:go 給Magento的模塊保存添加事務(transaction)