為啥用IDEA反編譯沒有擦除泛型?
??前言
Java泛型是進階高級開發必備技能之一,了解實現泛型的基本原理,有助于寫出更優質的代碼。
眾所周知,Java是偽泛型,是通過類型擦除(Type Erasure)來實現的。為了“查看/證明”Java對泛型類型的擦除,我們常常通過反編譯的手段實現。Intellij IDEA作為Java開發主流IDE,它內置的反編譯功能是最為常用的反編譯工具。
但是,你會發現,IDEA的反編譯竟沒有擦除泛型。
?正文
如下代碼:
我們借助IDEA的反編譯后的內容:找到需要反編譯的.class文件
雙擊即可查看:
我的天,泛型類型不應該被擦除了嗎,為毛還在?IDEA的反編譯工具難道有bug?
??嘗試其它反編譯工具
IDEA最初內置的是著名的JD-GUI?反編譯插件,從2016年起改為自研的反編譯插件Java Bytecode Decompiler,一直沿用至今:
為了驗證此問題,我計劃多試試幾款反編譯工具。
??jd-gui
下載地址:https://github.com/java-decompiler/jd-gui/releases
尷尬的是,雙擊打不開:
無奈。在虛擬機里啟了個Windows 11來跑:
結論:沒有擦除泛型類型。和IDEA不同的是它反編譯出來的結果更“原始”一丟丟
??jadx
下載地址:https://github.com/skylot/jadx/releases
同樣的Windows 11上運行進行反編譯:
結論:沒有擦除泛型類型。結果不說和IDEA差不多,也是一模一樣。
??JAD
下載地址:https://varaneckas.com/jad
由于我的本是基于Apple Silicon芯片的,所以只能繼續在Windows上執行了:
結論:泛型類型被擦除了。
??Beyond Compare 4
Beyond Compare的主業是做文件比較,其實它也可以Java反編譯。只需在https://www.scootersoftware.com/download.php?zz=moreformats下載所需插件:
使用Beyond Compare 4進行反編譯:
結論:泛型類型被擦除了。Beyond Compare 4的反編譯基于Jad,因此效果和Jad一模一樣
??javap -c
使用最底層的javap -c進行反編譯:
結論:泛型類型被擦除了。
??總結
有些擦除了但有些沒有擦除泛型類型,到底該信誰呢?當然是無條件相信javap -c,因為一切反編譯操作都基于它。so結論是:Java的泛型是偽泛型,編譯后泛型類型都會被擦除。
記住結論的同時,通過本文對比了多個反編譯器的結果亦可得到兩條基本的常識:
- 像IDEA內置的Java Bytecode Decompiler?以及jadx這種比較新(還在持續迭代)的工具,稱作智能反編譯器更為合適:它能重排序代碼,并且“保留”住泛型類型,方便開發者閱讀
- Java泛型引入至今已有近20年,“偽泛型”已被認為是所有開發者的共識,沒有必要再在反編譯后體現出來反倒大大降低了可讀性。像Jad這種“上古”時期的反編譯器,依舊原汁原味