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

前因

一直以來大家都說java的泛型是偽泛型,類型參數(shù)會在編譯階段進(jìn)行擦除,那么到底什么是所謂的泛型擦除呢,怎么去理解它?今天結(jié)合字節(jié)碼來一探究竟。

泛型擦除的含義

泛型中的類型參數(shù)只存在于編譯期,在運(yùn)行時,Java 的虛擬機(jī) ( 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>其實是對應(yīng)到同一個Class對象的,虛擬機(jī)在編譯的時候并沒有生成兩份class文件來對應(yīng)ArrayList<String>,ArrayList<Integer>。
看下上面這個類對應(yīng)的字節(jié)碼,確實是對應(yīng)到同一個符號鏈接。

ErasedTypeEquivalence的字節(jié)碼.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顯示的用了類型轉(zhuǎn)換來得到塞入的字符串。

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

字節(jié)碼中確實生成了checkcast指令:

Holder1的字節(jié)碼

運(yùn)用了泛型的Holder2,代碼相對來說簡潔一些,并不需顯示的來做類型轉(zhuǎn)換,編譯器自動為我們生成了相應(yīng)的類型轉(zhuǎn)換指令,這同時映證了在運(yùn)行時候jvm確實不知道泛型的類型信息。

字節(jié)碼如下:

Holder2的字節(jié)碼.png
Holder2的字節(jié)碼.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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 文章作者:Tyan博客:noahsnail.com 1. 什么是泛型 Java泛型(Generics)是JDK 5...
    SnailTyan閱讀 835評論 0 3
  • 泛型是Java 1.5引入的新特性。泛型的本質(zhì)是參數(shù)化類型,這種參數(shù)類型可以用在類、變量、接口和方法的創(chuàng)建中,分別...
    何時不晚閱讀 3,115評論 0 2
  • 附上思維導(dǎo)圖。這篇博客主要講了如下知識點。 看完了《Thinking in Java》的第十五章泛型,著實被震了一...
    Happioo閱讀 1,146評論 0 1
  • 1. 泛型概述 泛型(Generic type 或者 generics)是對 Java 語言的類型系統(tǒng)的一種擴(kuò)展,...
    JackChen1024閱讀 553評論 0 3
  • 你很努力的工作,可是成功總是一次次擦肩而過; 或是你渴望著婚姻,可是婚姻的大門始終為你關(guān)閉; 或是孩子的教育出現(xiàn)問...
    上海清悟閱讀 130評論 0 0

友情鏈接更多精彩內(nèi)容