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

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

示例代码:

    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为伪泛型语言
         */
    }

 

相关文章:

  • 2021-12-22
  • 2021-08-11
  • 2021-06-29
  • 2022-12-23
  • 2021-09-18
  • 2021-08-27
  • 2022-12-23
  • 2021-06-07
猜你喜欢
  • 2022-12-23
  • 2023-04-03
  • 2021-04-19
  • 2022-02-26
  • 2021-08-01
  • 2022-12-23
相关资源
相似解决方案