怎么理解Java中的泛型擦除?

前因

一直以来大家都说java的泛型是伪泛型,类型参数会在编译阶段进行擦除,那么到底什么是所谓的泛型擦除呢,怎么去理解它?今天结合字节码来一探究竟。

泛型擦除的含义

泛型中的类型参数只存在于编译期,在运行时,Java 的虚拟机 ( JVM ) 并不知道泛型的存在。

例子1

先看如下的代码,你觉得它的输出是'true'还是'false'。

public class ErasedTypeEquivalence {
 
    public static void main(String[] args) {
 
        Class c1 = new ArrayList<String>().getClass();
        Class c2 = new ArrayList<Integer>().getClass();
        System.out.println(c1 == c2);
 
    }
}

答案是true,也就是说ArrayList<String>和ArrayList<Integer>其实是对应到同一个Class对象的,虚拟机在编译的时候并没有生成两份class文件来对应ArrayList<String>,ArrayList<Integer>。
看下上面这个类对应的字节码,确实是对应到同一个符号链接。

ErasedTypeEquivalence的字节码.png

例子2

再来看一个例子:

public class Holder1 {
    private Object a;
 
    public Holder1(Object a) {
        this.a = a;
    }
 
    public Object get() {
        return this.a;
    }
 
    public void set(Object a) {
        this.a = a;
    }
 
 
    public static void main(String[] args) {
        Holder1 holder1 = new Holder1("test");
        String a = (String) holder1.get();
        System.out.println(a);
    }
}
public class Holder2<T> {
    private T a;
 
    public Holder2(T a) {
        this.a = a;
    }
 
    public T get() {
        return this.a;
    }
 
    public void set(T a) {
        this.a = a;
    }
 
    public static void main(String[] args) {
        Holder2<String> holder2 = new Holder2<>("test");
        String a = holder2.get();
        System.out.println(a);
    }
}

在上面的两个例子中,Holder1用一个Object的变量来持有对象,Holder2用了泛型。在main方法中,Holder1显示的用了类型转换来得到塞入的字符串。

String a = (String) holder1.get();

字节码中确实生成了checkcast指令:

Holder1的字节码

运用了泛型的Holder2,代码相对来说简洁一些,并不需显示的来做类型转换,编译器自动为我们生成了相应的类型转换指令,这同时映证了在运行时候jvm确实不知道泛型的类型信息。

字节码如下:

Holder2的字节码.png
Holder2的字节码.png

参考资料

1.https://segmentfault.com/a/1190000005179142
2.https://stackoverflow.com/questions/313584/what-is-the-concept-of-erasure-in-generics-in-java
3.Generics in the Java Programming Language
4.The Java Virtual Machine Specification Java SE 8 Edition

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 文章作者:Tyan博客:noahsnail.com 1. 什么是泛型 Java泛型(Generics)是JDK 5...
    SnailTyan阅读 788评论 0 3
  • 泛型是Java 1.5引入的新特性。泛型的本质是参数化类型,这种参数类型可以用在类、变量、接口和方法的创建中,分别...
    何时不晚阅读 3,058评论 0 2
  • 附上思维导图。这篇博客主要讲了如下知识点。 看完了《Thinking in Java》的第十五章泛型,着实被震了一...
    Happioo阅读 769评论 0 1
  • 1. 泛型概述 泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,...
    JackChen1024阅读 520评论 0 3
  • 你很努力的工作,可是成功总是一次次擦肩而过; 或是你渴望着婚姻,可是婚姻的大门始终为你关闭; 或是孩子的教育出现问...
    上海清悟阅读 110评论 0 0