使用IDEA反編譯沒有擦除泛型的原因解析
??前言
Java泛型是進(jìn)階高級(jí)開發(fā)必備技能之一,了解實(shí)現(xiàn)泛型的基本原理,有助于寫出更優(yōu)質(zhì)的代碼。
眾所周知,Java是偽泛型,是通過類型擦除(Type Erasure)來實(shí)現(xiàn)的。為了“查看/證明”Java對(duì)泛型類型的擦除,我們常常通過反編譯的手段實(shí)現(xiàn)。Intellij IDEA作為Java開發(fā)主流IDE,它內(nèi)置的反編譯功能是最為常用的反編譯工具。
但是,你會(huì)發(fā)現(xiàn),IDEA的反編譯竟沒有擦除泛型。
?正文
如下代碼:
/**
* 在此處添加備注信息
*
* @author YourBatman's home page. <a href=https://yourbatman.cn>https://yourbatman.cn</a>
* @author YourBatman. <a href=mailto:yourbatman@aliyun.com>Send email to me</a>
* @author wechat:fsx641385712
* @since 0.0.1
*/
public class Tester {
@Test
public void fun() {
List<Integer> numbers = new ArrayList<>();
numbers.add(18);
List newNumbers = numbers;
newNumbers.add("YourBatman");
System.out.println(numbers);
}
@Test
public void fun1() {
List<Integer> intList = new ArrayList<>();
List<String> stringList = new ArrayList<>();
System.out.println(intList.getClass() == stringList.getClass());
}
}我們借助IDEA的反編譯后的內(nèi)容:找到需要反編譯的.class文件

雙擊即可查看:

我的天,泛型類型不應(yīng)該被擦除了嗎,為毛還在?IDEA的反編譯工具難道有bug?
??嘗試其它反編譯工具
IDEA最初內(nèi)置的是著名的JD-GUI反編譯插件,從2016年起改為自研的反編譯插件Java Bytecode Decompiler,一直沿用至今:

為了驗(yàn)證此問題,我計(jì)劃多試試幾款反編譯工具。
??jd-gui
下載地址:https://github.com/java-decompiler/jd-gui/releases

尷尬的是,雙擊打不開:

無奈。在虛擬機(jī)里啟了個(gè)Windows 11來跑:

結(jié)論:沒有擦除泛型類型。和IDEA不同的是它反編譯出來的結(jié)果更“原始”一丟丟
??jadx
下載地址:https://github.com/skylot/jadx/releases

同樣的Windows 11上運(yùn)行進(jìn)行反編譯:

結(jié)論:沒有擦除泛型類型。結(jié)果不說和IDEA差不多,也是一模一樣。
??JAD
下載地址:https://varaneckas.com/jad

由于我的本是基于Apple Silicon芯片的,所以只能繼續(xù)在Windows上執(zhí)行了:

結(jié)論:泛型類型被擦除了。
??Beyond Compare 4
Beyond Compare的主業(yè)是做文件比較,其實(shí)它也可以Java反編譯。只需在https://www.scootersoftware.com/download.php?zz=moreformats下載所需插件:

使用Beyond Compare 4進(jìn)行反編譯:

結(jié)論:泛型類型被擦除了。Beyond Compare 4的反編譯基于Jad,因此效果和Jad一模一樣
??javap -c
使用最底層的javap -c進(jìn)行反編譯:

結(jié)論:泛型類型被擦除了。
??總結(jié)
有些擦除了但有些沒有擦除泛型類型,到底該信誰呢?當(dāng)然是無條件相信javap -c,因?yàn)橐磺蟹淳幾g操作都基于它。so結(jié)論是:Java的泛型是偽泛型,編譯后泛型類型都會(huì)被擦除。
記住結(jié)論的同時(shí),通過本文對(duì)比了多個(gè)反編譯器的結(jié)果亦可得到兩條基本的常識(shí):
- 像IDEA內(nèi)置的
Java Bytecode Decompiler以及jadx這種比較新(還在持續(xù)迭代)的工具,稱作智能反編譯器更為合適:它能重排序代碼,并且“保留”住泛型類型,方便開發(fā)者閱讀 - Java泛型引入至今已有近20年,“偽泛型”已被認(rèn)為是所有開發(fā)者的共識(shí),沒有必要再在反編譯后體現(xiàn)出來反倒大大降低了可讀性。像Jad這種“上古”時(shí)期的反編譯器,依舊原汁原味 推薦閱讀 IntelliJ IDEA 2022.3正式發(fā)布,配置云同步&支持Redis好用到炸
本專欄源代碼庫:https://github.com/yourbatman/yourbatman-999-question
到此這篇關(guān)于為啥用IDEA反編譯沒有擦除泛型的文章就介紹到這了,更多相關(guān)IDEA反編譯沒有擦除泛型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器操作
這篇文章主要介紹了Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
IntelliJ IDEA下自動(dòng)生成Hibernate映射文件以及實(shí)體類
這篇文章主要介紹了IntelliJ IDEA下自動(dòng)生成Hibernate映射文件以及實(shí)體類,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
Java微信公眾號(hào)模板消息推送功能實(shí)例代碼
這篇文章主要介紹了Java微信公眾號(hào)模板消息推送功能的相關(guān)資料,包括了公眾號(hào)開發(fā)者平臺(tái)的參數(shù)獲取、微信發(fā)送接口的實(shí)際調(diào)用、消息發(fā)送的util類、示例模板以及接口調(diào)用的示例,需要的朋友可以參考下2025-05-05
MyBatis中的XML實(shí)現(xiàn)和動(dòng)態(tài)SQL實(shí)現(xiàn)示例詳解
這篇文章主要介紹了MyBatis中的XML實(shí)現(xiàn)和動(dòng)態(tài)SQL實(shí)現(xiàn),我們可以將XML中重復(fù)出現(xiàn)的內(nèi)容提取出來放到sql標(biāo)簽中,當(dāng)需要用到sql標(biāo)簽中的內(nèi)容時(shí),用include標(biāo)簽將sql標(biāo)簽中的內(nèi)容引進(jìn)來即可,感興趣的朋友跟隨小編一起看看吧2024-02-02
Spring?Modulith模塊化單體應(yīng)用的概念和優(yōu)勢
本文將深入探討Spring?Modulith的核心概念、實(shí)現(xiàn)方式以及最佳實(shí)踐,幫助開發(fā)者構(gòu)建易于維護(hù)且具有良好擴(kuò)展性的現(xiàn)代Java應(yīng)用,感興趣的朋友一起看看吧2025-09-09
shardingjdbc之配置druid數(shù)據(jù)庫連接池過程
這篇文章主要介紹了shardingjdbc之配置druid數(shù)據(jù)庫連接池過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03
SpringBoot2.1 RESTful API項(xiàng)目腳手架(種子)項(xiàng)目
這篇文章主要介紹了SpringBoot2.1 RESTful API項(xiàng)目腳手架(種子)項(xiàng)目,用于搭建RESTful API工程的腳手架,只需三分鐘你就可以開始編寫業(yè)務(wù)代碼,不再煩惱于構(gòu)建項(xiàng)目與風(fēng)格統(tǒng)一,感興趣的小伙伴們可以參考一下2018-12-12
Java操作PDF文件實(shí)現(xiàn)簽訂電子合同詳細(xì)教程
這篇文章主要介紹了如何在PDF中加入電子簽章與電子簽名的過程,包括編寫Word文件、生成PDF、為PDF格式做表單、為表單賦值、生成文檔以及上傳到OBS中的步驟,需要的朋友可以參考下2025-01-01

