zoukankan      html  css  js  c++  java
  • java 泛型实现原理

    泛型思想最早在C++语言的模板(Templates)中产生,Java后来也借用了这种思想。虽然思想一致,但是他们存在着本质性的不同。

    C++中的模板是真正意义上的泛型,在编译时就将不同模板类型参数编译成对应不同的目标代码,List<Integer>和List<String>是两种不同的类型,这种泛型被称为真正泛型。

    这种泛型实现方式,会导致类型膨胀,因为要为不同具体参数生成不同的类。

    Java中List<Integer>和List<String>虽然在源代码中属于不同的类,但是编译后的字节码中,他们都被替换成原始类型,而两者的原始类型的一样的(List<Object>),所以在运行时,List<Integer>与List<String>就是同一个类。

    Java中的泛型是一种特殊的语法,通过类型擦除实现,这种泛型称为伪泛型。

    类型擦除,是指将泛型类型实例关联到同一份字节码上。编译器只为泛型类型生成一份字节码,并将其实例关联到这份字节码上。

    类型擦除的关键在于从泛型类型中清除类型参数的相关信息,并且再必要的时候添加类型检查和类型转换的方法。

            List<Integer> intList = new ArrayList<>();
            intList.add(3);
            List<String> strList  = new ArrayList<>();
            strList.add("Hello");
    
            System.out.println(intList.getClass() == strList.getClass());  // 输出结果为true

    intList与strList都属于同一个类。

    创建一个只能存储Integer的ArrayList对象,在add一个整型数值后,利用反射调用add(Object o)add一个asd字符串,此时运行代码不会报错,运行结果会打印出1和asd两个值。这时再里利用反射调用add(Integer o)方法,运行会抛出codeNoSuchMethodException异常。这充分证明了在编译后,擦除了Integer这个泛型信息,只保留了原始类型。

    创建一个List<Integer>对象intList,利用反射调用其add()方法,向intList中添加一个String类元素,运行代码不会报错。

            List<Integer> intList = new ArrayList<>();
            intList.add(3);
    
            intList.getClass().getMethod("add", Object.class).invoke(intList, "Hello");
            for (int i = 0; i < intList.size(); i++) {
                System.out.println(intList.get(i)); 
            }
    
            // 输出结果为
            // 3
            // Hello

    这说明在编译后,擦出了Integer这个泛型信息,intList为原始类型List<Object>。

    修改代码getMethod("add", Object.class),改为getMethod("add", Integer.class)

    //      NoSuchMethodException: 
            intList.getClass().getMethod("add", Integer.class).invoke(intList, "Hello");

    运行报错,intList的类List<Integer>中没有("add", Integer.class)方法,只有("add", Object.class)。

    自动类型转换

    Java的泛型除了类型擦除之外,还会自动生成checkcast指令进行强制类型转换。

            List<Integer> intList = new ArrayList<>();
            intList.add(3);
    
            int a = intList.get(0);

    使用intList的get方法返回的是Integer类型的对象。

  • 相关阅读:
    Finer Resolution Observation and Monitoring -Global Land Cover更精细的分辨率观测和监测-全球土地覆盖
    MapServer教程3
    手写Tomcat源码
    室内无线局域网
    基于点云的3ds Max快速精细三维建模方法及系统的制作方法 插件开发
    Web Mapping Illustrated Using Open Source GIS Toolkits
    apache Internal Server Error 解决方法
    php命令行工具
    小程序:将gbk转为utf-8
    java FileUtil(文件操作类)
  • 原文地址:https://www.cnblogs.com/deltadeblog/p/9222167.html
Copyright © 2011-2022 走看看