關(guān)于Java泛型"擦除"的一點(diǎn)思考

頭次寫(xiě)博客,想說(shuō)的東西不難,關(guān)于泛型的疑問(wèn),是前一陣在學(xué)習(xí)jackson中遇到的。

下面就把我所想到的、遇到的,分享出來(lái)。

泛型是JDK1.5后的一個(gè)特性,是一個(gè)參數(shù)類(lèi)型的應(yīng)用,可以將這個(gè)參數(shù)聲明在類(lèi)、接口、方法中,就像我們方法中定義的局部變量一樣;在工作中,我們常在List,Map,Set等集合對(duì)象中使用,或者我們自己聲明的類(lèi)中使用。

說(shuō)到泛型,就不得說(shuō)起“擦除”這個(gè)概念,相比于c#來(lái)說(shuō),java的泛型只存在于程序的源碼中,在編譯后的class文件中不存在,這個(gè)過(guò)程就是--泛型"擦除";所以,對(duì)于new ArrayList<String> 和 new ArrayList<Integer> 來(lái)說(shuō),兩個(gè)對(duì)象在編譯之后兩者是一樣的,通過(guò)反射均可以向集合中添加任意類(lèi)型的對(duì)象;

可以看到,在編譯后的class文件中,ArrayList所聲明的泛型不存在了;由此可知,如果想在程序運(yùn)行期間獲取泛型,看似是一件不可能完成的事情!

直到學(xué)習(xí)了jackson后,我發(fā)現(xiàn)java泛型的“擦除”并不能一概而論;至少通過(guò)TypeReference接口,是可以獲取到對(duì)象中的泛型;


一開(kāi)始學(xué)習(xí)jackson,相關(guān)的api操作還不是很熟悉,json并沒(méi)有轉(zhuǎn)換成StudentEntity對(duì)象,而是變成了LinkedHashMap;研究后,發(fā)現(xiàn)可以使用TypeReference對(duì)象,來(lái)實(shí)現(xiàn)參數(shù)化類(lèi)型的json轉(zhuǎn)換;


有些疑問(wèn)?按照之前所說(shuō),由于泛型“擦除”的原因,泛型在編譯后的class文件中就不存在了,只會(huì)保留原始類(lèi)型(Type中的概念),那么TypeReference又是如何實(shí)現(xiàn),獲取到了具體的泛型類(lèi)型呢!

查看TypeReference的源碼,發(fā)現(xiàn)在其構(gòu)造方法中,主要使用到了getGenericSuperclass()和getActualTypeArguments
()兩個(gè)方法,getGenericSuperclass()返回的是此對(duì)象帶“泛型”的父類(lèi),而getActualTypeArguments()返回的是此父類(lèi)中實(shí)際類(lèi)型參數(shù)的Type 對(duì)象數(shù)組,說(shuō)白了就是TypeReference<>中的泛型;

通過(guò)debug,發(fā)現(xiàn)確實(shí)獲取到了new TypeReference<Map<String,StudentEntity>>中的泛型,至此我決定自己寫(xiě)個(gè)父類(lèi)、子類(lèi),看看效果如何?


再次通過(guò)debug發(fā)現(xiàn),并沒(méi)有得到具體的泛型,而是獲取到了ParameterizedTypeImpl對(duì)象(Type中的概念);此時(shí),對(duì)于泛型更加疑惑了,感覺(jué)心中有千萬(wàn)只草泥馬在奔騰!

于是,又回過(guò)頭來(lái)看了下之前的代碼 new TypeReference<Map<String,StudentEntity>>(){},發(fā)現(xiàn)此段代碼其實(shí)是一個(gè)匿名的內(nèi)部類(lèi),而編譯器在編譯的時(shí)候,會(huì)將此匿名內(nèi)部類(lèi)單獨(dú)生成一個(gè)class文件,命名規(guī)則如下:主類(lèi)+$+(1,2,3....)


通過(guò)反編譯后,真相一目了然!


創(chuàng)建的匿名內(nèi)部類(lèi)new TypeReference<Map<String,StudentEntity>>(){},在生成的的class文件中,編譯器默認(rèn)為T(mén)ypeReference中的泛型Map<String,StudentEntity>原始類(lèi)型,并不會(huì)進(jìn)行擦除!類(lèi)似于 我們實(shí)際創(chuàng)建一個(gè)類(lèi) Class TypeReference<Map<String,StudentEntity>>{}?、 Class Test<T>{}一樣,在編譯后Map、T依舊會(huì)存在!

由此,對(duì)于java泛型的“擦除”并不能一概而論,在運(yùn)行期間,如果方法中出現(xiàn)帶泛型的匿名內(nèi)部類(lèi),那么泛型依舊會(huì)被保留下來(lái),我們可以通過(guò)對(duì)應(yīng)的方法獲取到實(shí)際的泛型類(lèi)型!

上文中,提到的Type、原始類(lèi)型的概念,在下一篇博客中提及!

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

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類(lèi)相關(guān)的語(yǔ)法,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線(xiàn)程的語(yǔ)...
    子非魚(yú)_t_閱讀 34,623評(píng)論 18 399
  • 一、基本數(shù)據(jù)類(lèi)型 注釋 單行注釋?zhuān)?/ 區(qū)域注釋?zhuān)?* */ 文檔注釋?zhuān)?** */ 數(shù)值 對(duì)于byte類(lèi)型而言...
    龍貓小爺閱讀 4,434評(píng)論 0 16
  • 對(duì)象的創(chuàng)建與銷(xiāo)毀 Item 1: 使用static工廠(chǎng)方法,而不是構(gòu)造函數(shù)創(chuàng)建對(duì)象:僅僅是創(chuàng)建對(duì)象的方法,并非Fa...
    孫小磊閱讀 2,177評(píng)論 0 3
  • 第六章 這是一場(chǎng)服裝發(fā)布會(huì),發(fā)布的是今年最新款的夏裝,期間還有欣賞類(lèi)服裝的表演。 夏季服裝輕薄透,最容易探出他的取...
    霜紅秋葉閱讀 177評(píng)論 0 1
  • 那時(shí)候的人啊,想法就那么質(zhì)樸簡(jiǎn)單,可是又那么單純美好。說(shuō)到這里,董姨無(wú)限感慨。是啊,關(guān)于愛(ài)情的表達(dá)方式,也許沉默才...
    小花fayer閱讀 618評(píng)論 0 0

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