頭次寫博客溃列,想說的東西不難,關(guān)于泛型的疑問膛薛,是前一陣在學(xué)習(xí)jackson中遇到的听隐。
下面就把我所想到的、遇到的哄啄,分享出來雅任。
泛型是JDK1.5后的一個(gè)特性,是一個(gè)參數(shù)類型的應(yīng)用咨跌,可以將這個(gè)參數(shù)聲明在類沪么、接口、方法中锌半,就像我們方法中定義的局部變量一樣禽车;在工作中,我們常在List刊殉,Map殉摔,Set等集合對(duì)象中使用,或者我們自己聲明的類中使用记焊。
說到泛型逸月,就不得說起“擦除”這個(gè)概念,相比于c#來說亚亲,java的泛型只存在于程序的源碼中彻采,在編譯后的class文件中不存在,這個(gè)過程就是--泛型"擦除"捌归;所以肛响,對(duì)于new ArrayList<String> 和 new ArrayList<Integer> 來說,兩個(gè)對(duì)象在編譯之后兩者是一樣的惜索,通過反射均可以向集合中添加任意類型的對(duì)象特笋;
可以看到,在編譯后的class文件中,ArrayList所聲明的泛型不存在了猎物;由此可知虎囚,如果想在程序運(yùn)行期間獲取泛型,看似是一件不可能完成的事情蔫磨!
直到學(xué)習(xí)了jackson后淘讥,我發(fā)現(xiàn)java泛型的“擦除”并不能一概而論;至少通過TypeReference接口堤如,是可以獲取到對(duì)象中的泛型蒲列;
一開始學(xué)習(xí)jackson,相關(guān)的api操作還不是很熟悉搀罢,json并沒有轉(zhuǎn)換成StudentEntity對(duì)象蝗岖,而是變成了LinkedHashMap;研究后榔至,發(fā)現(xiàn)可以使用TypeReference對(duì)象抵赢,來實(shí)現(xiàn)參數(shù)化類型的json轉(zhuǎn)換;
有些疑問唧取?按照之前所說铅鲤,由于泛型“擦除”的原因,泛型在編譯后的class文件中就不存在了枫弟,只會(huì)保留原始類型(Type中的概念)彩匕,那么TypeReference又是如何實(shí)現(xiàn),獲取到了具體的泛型類型呢媒区!
查看TypeReference的源碼,發(fā)現(xiàn)在其構(gòu)造方法中掸犬,主要使用到了getGenericSuperclass()和getActualTypeArguments
()兩個(gè)方法袜漩,getGenericSuperclass()返回的是此對(duì)象帶“泛型”的父類,而getActualTypeArguments()返回的是此父類中實(shí)際類型參數(shù)的Type 對(duì)象數(shù)組湾碎,說白了就是TypeReference<>中的泛型宙攻;
通過debug,發(fā)現(xiàn)確實(shí)獲取到了new TypeReference<Map<String,StudentEntity>>中的泛型,至此我決定自己寫個(gè)父類介褥、子類座掘,看看效果如何?
再次通過debug發(fā)現(xiàn)柔滔,并沒有得到具體的泛型溢陪,而是獲取到了ParameterizedTypeImpl對(duì)象(Type中的概念);此時(shí)睛廊,對(duì)于泛型更加疑惑了形真,感覺心中有千萬只草泥馬在奔騰!
于是超全,又回過頭來看了下之前的代碼 new TypeReference<Map<String,StudentEntity>>(){}咆霜,發(fā)現(xiàn)此段代碼其實(shí)是一個(gè)匿名的內(nèi)部類邓馒,而編譯器在編譯的時(shí)候,會(huì)將此匿名內(nèi)部類單獨(dú)生成一個(gè)class文件蛾坯,命名規(guī)則如下:主類+$+(1,2,3....)
通過反編譯后光酣,真相一目了然!
創(chuàng)建的匿名內(nèi)部類new TypeReference<Map<String,StudentEntity>>(){}脉课,在生成的的class文件中救军,編譯器默認(rèn)為TypeReference中的泛型Map<String,StudentEntity>原始類型,并不會(huì)進(jìn)行擦除下翎!類似于 我們實(shí)際創(chuàng)建一個(gè)類 Class TypeReference<Map<String,StudentEntity>>{}?缤言、 Class Test<T>{}一樣,在編譯后Map视事、T依舊會(huì)存在胆萧!
由此,對(duì)于java泛型的“擦除”并不能一概而論俐东,在運(yùn)行期間跌穗,如果方法中出現(xiàn)帶泛型的匿名內(nèi)部類,那么泛型依舊會(huì)被保留下來虏辫,我們可以通過對(duì)應(yīng)的方法獲取到實(shí)際的泛型類型蚌吸!
上文中,提到的Type砌庄、原始類型的概念羹唠,在下一篇博客中提及!