泛型可以理解为在类上贴了一个标签,作用是编译器通过标签确定类型。在底层运行时会先执行一个“类型擦除”的操作
那么有什么方法可以使类跳过泛型检查呢?我们可以使用反射使类在编译的时候越过泛型检查。
示例代码:
public static void main(String[] args)throws Exception { List<String> list = new ArrayList<>(); list.add("字符串1"); list.add("字符串2"); list.add("字符串3"); //在list上有泛型限制,限制这个list对象的类型为String // list.add(11);//添加一个Integer类型数据会报编译时错误 /** * 那我们如何在list中添加一个Integer类型的数据呢? * 可以使用反射进行添加 */ //获取list集合的对象,因为要操作对象,所以直接只用.getClass获取对象的字节码文件 Class<?> listObject = list.getClass(); //得到list对象的add方法 Method listAddMethod = listObject.getDeclaredMethod("add",Object.class); //往数组中添加Integer类型数据 listAddMethod.invoke(list,11); listAddMethod.invoke(list,22); listAddMethod.invoke(list,33); for (Object e : list){ //字符串1 字符串2 字符串3 11 22 33 ,完成添加 System.out.print(e + " "); } /** * 解释:因为泛型信息只存在于代码编译阶段,编译器编译完成带有泛型的java程序后, * 生成的class文件中与泛型相关的信息就会被擦除,以此使程序执行效率不受影响,这个过程 * 叫做泛型的类型擦除,也就是说泛型类型和普通类在java虚拟机内是一样的。 * 在本例中,list<String> 与List<Integer>经过编译的类型擦除后,类型均为java.util.ArrayList * 由于编译生成的字节码文件会丢失泛型的类型信息,只要能跳过编译器,就可以往某个泛型 * 集合中添加其他类型的数据(通过反射获取类的字节码文件,获取这个对象的添加方法) * 这也就是我们为什么称java为伪泛型语言 */ }