美文网首页
怎么理解Java中的泛型擦除?

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

作者: 兰塔项 | 来源:发表于2017-07-02 17:39 被阅读0次

前因

一直以来大家都说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

相关文章

  • java_泛型

    类型擦除正确理解泛型概念的首要前提是理解类型擦除(type erasure)。 Java中的泛型基本上都是在编译器...

  • Android 开发也要掌握的Java知识 - Java泛型

    如果需要看泛型擦除Java泛型擦除 1.Java泛型有什么用?为啥要使用泛型? Java中数组的类型是定义的时候就...

  • 【进阶之路】Java的类型擦除式泛型

    【进阶之路】Java的类型擦除式泛型 Java选择的泛型类型叫做类型擦除式泛型。什么是类型擦除式泛型呢?就是Jav...

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

    前因 一直以来大家都说java的泛型是伪泛型,类型参数会在编译阶段进行擦除,那么到底什么是所谓的泛型擦除呢,怎么去...

  • Java 泛型与通配符

    参考地址:《Java 泛型,你了解类型擦除吗?》 《Java中的逆变与协变》 《java 泛型中 T、E .....

  • 泛型中 ? super T和 ? extends T的区别

    首先, 说到 Java 的泛型, 我们必须要提到的是Java 泛型的类型擦除机制: Java中的泛型基本上都是在编...

  • Java 泛型擦除原理

    问:请比较深入的谈谈你对 Java 泛型擦除的理解和带来的问题认识? 答:Java 的泛型是伪泛型,因为在编译期间...

  • Java泛型:类型擦除

    前情回顾 Java泛型:泛型类、泛型接口和泛型方法 类型擦除 代码片段一 显然在平时使用中,ArrayList (...

  • java泛型背后是什么

    这一节主要讲的内容是java中泛型的应用,通过该篇让大家更好地理解泛型,以及面试中经常说的泛型类型擦除是什么概念,...

  • java的泛型机制

    <1>:java的泛型机制是javase1.5引入的 <2>:泛型擦除的概念:java中的泛型在编译之后生成的字节...

网友评论

      本文标题:怎么理解Java中的泛型擦除?

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