跳过编译器,获取泛型参数的实际类型

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的源代码:

跳过编译器,获取泛型参数的实际类型_第1张图片
 

你可能感兴趣的:(编译器)