• 泛型中的类型擦除


    通过反射理解泛型的本质(类型擦除)

    Java中的泛型是通过类型擦除来实现的。所谓类型擦除,是指通过类型参数合并,将泛型类型实例关联到同一份字节码上。编译器只为泛型类型生成一份字节码,并将其实例关联到这份字节码上。类型擦除的关键在于从泛型类型中清除类型参数的相关信息,并且再必要的时候添加类型检查和类型转换的方法。

    下面通过两个例子来证明在编译时确实发生了类型擦除。

    例1分别创建实际类型为String和Integer的ArrayList对象,通过getClass()方法获取两个实例的类,最后判断这个实例的类是相等的,证明两个实例共享同一个类。

    // 声明一个具体类型为String的ArrayList
    ArrayList<String> arrayList1 = new ArrayList<String>();  
    arrayList1.add("abc");  
    
    // 声明一个具体类型为Integer的ArrayList
    ArrayList<Integer> arrayList2 = new ArrayList<Integer>();  
    arrayList2.add(123);  
    
    System.out.println(arrayList1.getClass() == arrayList2.getClass());  // 结果为true

    例2创建一个只能存储Integer的ArrayList对象,

          1、正常添加Integer

          2、使用Object.class  作为参数类型,利用反射添加  Integer , 利用反射添加  String

          3、以Integer.class 作为参数类型, 利用反射添加Integer , NoSuchMethodException

    说明编译后的泛型中只保留了 Object 作为参数类型,擦除了Integer 这个泛型信息。

    说明泛型只是为了防止输入出错,只在编译期有用,可以利用反射绕过编译期。

        public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            ArrayList<Integer> arrayList3 = new ArrayList<Integer>();
            arrayList3.add(1);
    //        arrayList3.getClass().getMethod("add", Object.class).invoke(arrayList3, "一");
            System .out.println("输出一:");
            for (int i = 0; i < arrayList3.size(); i++) {
                System.out.println(arrayList3.get(i)); // 输出
            }
            arrayList3.getClass().getMethod("add", Object.class).invoke(arrayList3, 2); // 使用Object.class 可以add  Integer
            arrayList3.getClass().getMethod("add", Object.class).invoke(arrayList3, "二"); // 使用Object.class 可以add  String
    
            System.out.println("输出二:");
            for (int i = 0; i < arrayList3.size(); i++) {
                System.out.println(arrayList3.get(i)); // 输出
            }
    
    
            System.out.println("输出三:");
            arrayList3.getClass().getMethod("add", Integer.class).invoke(arrayList3, 3); // 使用Integer.class   NoSuchMethodException:java
    
        }


     
     
     

    在泛型中并不存在具体的类型

     
    public class E <T> {
      T t ;
    
      public E(T t) {
        this.t = t;
      }
      public void add(T t){
        this.t =t;
      }
      static public void main(String... args){
        E e = new E("A");
        System.out.println(e.t.getClass());
        e.add(1);
        System.out.println(e.t.getClass());
      }
    }

    输出结果:

    class java.lang.String
    class java.lang.Integer
     
     
     
     
  • 相关阅读:
    web.xml中<web-app>报错
    groovy初体验:groovy在java中的应用
    Mac安装JMeter时Unable to access jarfile ./ApacheJMeter.jar 解决方法
    intellij idea中解决java.lang.VerifyError: Expecting a stackmap frame at branch target的方法
    关于go get无法安装国内被墙软件解决办法
    Oracle 序列
    无锁并发框架Disruptor学习入门
    vsftp服务器部署
    FinalShell 推荐
    supperset (python 2.7.12 + mysql)记录
  • 原文地址:https://www.cnblogs.com/the-wang/p/10234727.html
Copyright © 2020-2023  润新知