美文网首页学习
深入理解Java中的泛型(三)泛型类型擦除与泛型转译

深入理解Java中的泛型(三)泛型类型擦除与泛型转译

作者: 不思进取的码农 | 来源:发表于2021-08-23 14:36 被阅读0次

    什么是泛型类型擦除

    先看一道经典的测试题

    List<String> list1 = new ArrayList<String>(); 
    List<Integer> list2 = new ArrayList<Integer>();
    System.out.println(list1getClass() == list1.getClass()); 
    

    上面代码最终结果输出的是什么?不了解泛型的和很熟悉泛型的同学应该能够答出来,而对泛型有所了解,但是了解不深入的同学可能会答错。

    正确答案是 true。

    上面的代码中涉及到了泛型,而输出的结果缘由是类型擦除

    简单概括泛型的类型擦除
    泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。

    通过泛型转译来解决类型擦除问题

    public class Erasure <T>{
        T object;
    
        public Erasure(T object) {
            this.object = object;
        }
        
    }
    

    Erasure 是一个泛型类,我们查看它在运行时的状态信息可以通过反射

    Erasure<String> erasure = new Erasure<String>("hello");
     Class eclz = erasure.getClass(); 
    System.out.println("erasure class is:"+eclz.getName());
    

    打印的结果是

    erasure class is:com.frank.test.Erasure
    

    Class 的类型仍然是 Erasure 并不是 Erasure<T>这种形式,那我们再看看泛型类中 T 的类型在 jvm 中是什么具体类型。

    Field[] fs = eclz.getDeclaredFields();
    for ( Field f:fs) {
        System.out.println("Field name "+f.getName()+" type:"+f.getType().getName());
    }
    

    打印结果是

    Field name object type:java.lang.Object
    

    那我们可不可以说,泛型类被类型擦除后,相应的类型就被替换成 Object 类型呢?

    这种说法,不完全正确。

    我们更改一下代码。

    public class Erasure <T extends String>{
    //  public class Erasure <T>{
        T object;
    
        public Erasure(T object) {
            this.object = object;
        }
        
    }
    

    现在再看测试结果:

    Field name object type:java.lang.String
    

    我们现在可以下结论了,在泛型类被类型擦除的时候,之前泛型类中的类型参数部分如果没有指定上限,如<T>则会被转译成普通的 Object 类型,如果指定了上限如<T extends String>则类型参数就被替换成类型上限。

    相关文章

      网友评论

        本文标题:深入理解Java中的泛型(三)泛型类型擦除与泛型转译

        本文链接:https://www.haomeiwen.com/subject/srilbltx.html