泛型的实质

泛型可以理解为在类上贴了一个标签,作用是编译器通过标签确定类型。在底层运行时会先执行一个“类型擦除”的操作

那么有什么方法可以使类跳过泛型检查呢?我们可以使用反射使类在编译的时候越过泛型检查。

示例代码:

    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为伪泛型语言
         */
    }
原文地址:https://www.cnblogs.com/huanghuanghui/p/10164218.html