zoukankan      html  css  js  c++  java
  • 泛型中的类型擦除

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

    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
     
     
     
     
  • 相关阅读:
    398. Random Pick Index
    382. Linked List Random Node
    645. Set Mismatch
    174. Dungeon Game
    264. Ugly Number II
    115. Distinct Subsequences
    372. Super Pow
    LeetCode 242 有效的字母异位词
    LeetCode 78 子集
    LeetCode 404 左叶子之和
  • 原文地址:https://www.cnblogs.com/the-wang/p/10234727.html
Copyright © 2011-2022 走看看