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

什么是泛型类型擦除

先看一道经典的测试题

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>则类型参数就被替换成类型上限。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 文章开始的地方,先给大家奉上一道经典的测试题。 请问,上面代码最终结果输出的是什么?不了解泛型的和很熟悉泛型的同学...
    as_pixar阅读 2,900评论 0 0
  • 泛型,一个孤独的守门者。 大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛...
    程序员BUG阅读 2,806评论 0 0
  • 泛型,一个孤独的守门者。 大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛...
    传奇内服号阅读 3,068评论 0 0
  • 类型擦除 泛型是 Java 1.5 版本才引进的概念,在这之前是没有泛型的概念的,但显然,泛型代码能够很好地和之前...
    Madu阅读 3,690评论 0 0
  • 泛型是什么? 泛型的英文是 generics,generic 的意思是通用,而翻译成中文,泛应该意为广泛,型即是类...
    五十米_深蓝阅读 4,709评论 0 20