記錄一下今天在幫同事解決使用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里面的元素居然是LinkedHashMap7怙薄!看著debug顯示的數(shù)據(jù)膘螟,簡(jiǎn)直不能接受成福,我明明聲明了rules對(duì)象只能存Rules對(duì)象啊,怎么會(huì)裝其他對(duì)象>2小奴艾!
然后就真的沒(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)題7殴搿!而且這種坑當(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)屬性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上是LinkedHashMapA椤U锇!所以spring可能并不支持泛型參數(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)昂勉。