Java 基礎 - Java為什么要類型擦除?


總結

一句話:為了兼容JDK 5 之前(有泛型功能之前)的項目,否則有大量代碼修改的工作。

 

1-“真泛型”是怎么操作的?

  • 若 Java 語言實現"真泛型",對泛型類型(泛型類、泛型接口)、泛型方法的名字使用特別的編碼,例如將 Factory<T> 類生成為一個名為 “Factory@@T” 的類,這種特別的編碼后的名字將被編譯器識別,作為判斷是否為泛型的依據。
  • 如果編譯時發現有對 Factory<String> 的使用,則將 “Factory@@T” 的所有邏輯復制一份,新建 “Factory@String@” 類,將原本的占位符 T 替換為 String 。然后在編譯 new Factory<String>() 時生成 new Factory@String@() 即可。

2-“真泛型”會導致什么后果?

  • 2.1 大規模的代碼修改
    • 假設A調用B1 lib,然后B1 lib遷移到了Java 5,並使用了泛型。那么A 也必須升級到Java 5,並修改代碼。在 Java 中不支持高版本的 Java 編譯生成的 class 文件在低版本的 JRE 上運行,如果嘗試這么做,就會得到 UnsupportedClassVersionError 錯誤。如下圖所示:

 

 

 2.2 非泛型類型和泛型不匹配

在 A 項目中,A 項目引用了 B1 lib 中的 ArrayList(用 list 變量記錄),那么假設 A 項目升級到 Java 5 后,還是引用的 B1 lib,那么必然會出現如下這種情況:

下述代碼中,A 項目將泛化后 ArrayList<T> 的傳遞給了 B1 lib 中的 ArrayList。

ArrayList list = new ArrayList<String>();
  • 左邊:B1 lib 中的老版本 ArrayList
  • 右邊:A 項目 中的新泛型版本 ArrayList<T>

這種情況的出現,會導致一個問題。就是 b1 項目中的 ArrayList 是不知道 A 項目中的 Arraylist 已經泛型化了的,那么如何保證泛型化后的 ArrayList(也就是ArrayList<T>)與老版本的 ArrayList 等價呢?
如果按照我們之前講解的 “真泛型” 思路來處理 Java 的泛型, 那么 new ArrayList<String>() 實際會被替換為 new ArrayList@String@(),那么實際運行代碼是這樣:

ArrayList list = new ArrayList@String@()

從代碼邏輯上來看,根本就跑不通。因為 ArrayList 與 ArrayList@String@ 根本就不是同一類, 那怎么辦呢?
最為直接的解決方案就是,不再為參數化類型創造新類了,同時在編譯期間將泛型類型中的類型參數全部替換 Object(因為不創建新類了,那么在泛型類中的 T 對應的類型,只能用 Object 替換)。

 

3-為了兼容JDK 5 之前的項目

通過編譯器的”魔法“,Java 就解決了處理泛型兼容老版本的問題。

//編譯器的代碼
 Node node = new Node<String>();
 //編譯后的代碼
 Node node = new Node();

 

 

參考文獻

作者:AndyJennifer
鏈接:https://juejin.cn/post/6844904134273925134
來源:掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM