1、我们都知道泛型出现的原因主要是为了统一集合中的数据类型,防止添加进集合中的数据不统一,导致在从集合中取数据的时候只能取到Object类型的,到时候需要进行复杂的强制类型转换,而直接强转是有风险的,所以为了使代码更加的规范,或者说避免出现失误,就出现了泛型。
2、泛型只会在编译阶段起作用,运行的时候就会被擦除掉,也就是说当你往集合中放数据的时候,泛型会进行限制你存放数据的类型,如果你存放的数据类型不符合规范,在编译期就会报错,如果通过了编译期之后进入运行状态的时候,泛型就不会起作用了。(可以通过反编译查看.class文件,会发现反编译出来的代码是不带泛型的)
3、所以我们可以使用反射机制来越过泛型的检查,是什么意思呢,就是说通过反射来调用集合类中的方法来往集合中存放数据,这个时候,泛型就对我们添加的数据不起作用了。这是为什么呢?因为我们使用反射机制的时候,是不是拿的是字节码文件的对象?而字节码文件是不是java文件编译之后的文件,所以我们使用字节码文件对象来调用方法的时候,泛型是已经不起作用了的,所以这个时候我们就可以往集合中添加其他类型的数据。
4、把泛型拦截在了编译阶段,在虚拟机中,所有的泛型参数最终的类型都会是转换后的Object类型(如果有类型限定,则是限定后的类型,如 <T extends Super>,则泛型T在虚拟机中统一都是Super类型),然后利用协变性而兼容所有类型或限定类型参数的传入,从而实现泛型。
代码演示:
public class Test1 {
public static void main(String[] args) throws Exception {
ArrayList<Integer> list = new ArrayList<>();
list.add(100);
list.add(123);
//list.add("Hello World!"); //不允许添加字符串
Class clazz = Class.forName("java.util.ArrayList"); //获取字节码对象
Method m = clazz.getMethod("add", Object.class); //获取add()方法
m.invoke(list, "Hello World");
System.out.println(list);
}
}