跳了一次JAVA泛型擦除的坑

記錄一下今天在幫同事解決使用spring參數(shù)注入問(wèn)題的時(shí)候由于對(duì)泛型的理解不到位而遇到的坑。

如下代碼所示:


@RequestMapping(value="saveAll")

public ResponseMsg saveAll(List rules){

Rule rule=rules.get(0);    //這行代碼在測(cè)試的時(shí)候報(bào)錯(cuò)了

......

}

這段代碼的意思是使用spring的參數(shù)注入功能自動(dòng)完成將前端傳過(guò)來(lái)的數(shù)據(jù)裝載到rules變量里面。

我剛開(kāi)始一直認(rèn)為這段代碼肯定是對(duì)的,然后就一直說(shuō)同事一定是前端傳過(guò)來(lái)的數(shù)據(jù)有錯(cuò),然后就各種檢查js,debug一步一步的查,發(fā)現(xiàn)前端傳過(guò)來(lái)的數(shù)據(jù)是正確的,后來(lái)我又想會(huì)不會(huì)是eclipse的debug功能有缺陷(原諒一個(gè)idea粉對(duì)eclipse的各種不屑),當(dāng)然繼續(xù)被打臉,因?yàn)槲以谖译娔X上debug時(shí)數(shù)據(jù)是一樣的,rules里面的元素居然是LinkedHashMap??!看著debug顯示的數(shù)據(jù),簡(jiǎn)直不能接受,我明明聲明了rules對(duì)象只能存Rules對(duì)象啊,怎么會(huì)裝其他對(duì)象?。?/p>

然后就真的沒(méi)轍了。。我就說(shuō)這個(gè)問(wèn)題我解決不了了,超出我認(rèn)知范圍啊,然后我們叫了一個(gè)正式員工過(guò)來(lái)幫我們看看。。他開(kāi)始也是按我們的步驟排錯(cuò),后來(lái)遇到和我們一樣的問(wèn)題,但是牛人終究是牛人,能想出來(lái)的導(dǎo)致問(wèn)題的因素也比我們多,他說(shuō)會(huì)不會(huì)是spring不支持這種帶泛型的自動(dòng)參數(shù)裝載啊,畢竟泛型是要被擦除的。。

擦除。。。泛型擦除。。。我靠,我終于知道是什么原因了。之前看了那么多關(guān)于泛型擦除的居然都沒(méi)有想到是這個(gè)問(wèn)題!!而且這種坑當(dāng)時(shí)也踩過(guò),居然沒(méi)聯(lián)想起來(lái),智商捉急。

關(guān)于泛型擦除的詳細(xì)介紹具體是什么我就不寫(xiě)在這篇文章里面了,大概就是在編譯前會(huì)執(zhí)行一系列的語(yǔ)法檢查,從而減少因?yàn)閺?qiáng)制類型轉(zhuǎn)換帶來(lái)的異常,但是編譯后的代碼是不含泛型的,會(huì)將泛型限制的元素類型給去掉。

也就是說(shuō)雖然我聲明了rules只能裝Rule類型的對(duì)象,但是代碼被編譯后,這個(gè)限制就沒(méi)有了!因?yàn)橥ㄟ^(guò)語(yǔ)法檢查rules里的元素確實(shí)是Rule類型的對(duì)象,所以并不需要在編譯后再去檢查。但是問(wèn)題來(lái)了,這種檢查只能檢查一些顯式生命的對(duì)象是不是Rule類型,而java是可以通過(guò)反射來(lái)動(dòng)態(tài)的生成對(duì)象的,sprng在參數(shù)注入的時(shí)候是通過(guò)反射實(shí)現(xiàn)前端參數(shù)自動(dòng)裝載入對(duì)象的相關(guān)屬性!!

所以這樣聲明的問(wèn)題在于,由于編譯時(shí)對(duì)rules內(nèi)元素類型的限制已經(jīng)被擦除了,所以spring并不知道反射成那種類型的對(duì)象,于是就默認(rèn)的用LinkedHashMap來(lái)裝載一個(gè)對(duì)象所有的屬性和值,于是rules里面的對(duì)象在運(yùn)行的時(shí)候?qū)嶋H上是LinkedHashMap?。。∷詓pring可能并不支持泛型參數(shù)或者需要指定其他條件才能正確的注入泛型參數(shù)(這個(gè)還沒(méi)有深究)。

至于以前踩過(guò)這方面的坑就是用Gson反序列化帶泛型的對(duì)象的時(shí)候需要額外指定一個(gè)參數(shù)來(lái)說(shuō)明集合里面的元素類型(具體的我忘了,這個(gè)有思路就好)。當(dāng)時(shí)也是覺(jué)得很奇妙,為什么不做得智能一點(diǎn)自己識(shí)別,我不是已經(jīng)通過(guò)泛型指定類型了么。當(dāng)時(shí)也就抱怨一下,沒(méi)有怎么多想,現(xiàn)在想起來(lái)還真是too young , too simple。。

這件事讓我明白不要盲目的相信自己的經(jīng)驗(yàn),計(jì)算機(jī)肯定是對(duì)的。經(jīng)驗(yàn)解決不了的問(wèn)題,就從原理一步一步去想,平時(shí)學(xué)的理論可能看起來(lái)沒(méi)什么用,就好像科普一樣,然而在解決一些問(wèn)題時(shí)確是一針見(jiàn)血。多聯(lián)想,發(fā)散思維才能在技術(shù)這條路上走得更遠(yuǎn)。

最后編輯于
?著作權(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)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,502評(píng)論 19 139
  • 文章作者:Tyan博客:noahsnail.com 1. 什么是泛型 Java泛型(Generics)是JDK 5...
    SnailTyan閱讀 835評(píng)論 0 3
  • 前面,由于對(duì)泛型擦除的思考,引出了對(duì)Java-Type體系的學(xué)習(xí)。本篇,就讓我們繼續(xù)對(duì)“泛型”進(jìn)行研究: JDK1...
    賈博巖閱讀 5,292評(píng)論 3 29
  • 泛型是Java 1.5引入的新特性。泛型的本質(zhì)是參數(shù)化類型,這種參數(shù)類型可以用在類、變量、接口和方法的創(chuàng)建中,分別...
    何時(shí)不晚閱讀 3,112評(píng)論 0 2
  • 如果 你不快樂(lè), 那就出去走走。 世界這么大, 風(fēng)景很美,機(jī)會(huì)很多, 人生很短,不要蜷縮在一處陰影中。
    我有念念不忘的遠(yuǎn)方閱讀 129評(píng)論 0 1

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