2023-01-06
泛型 類(lèi)型
一. 代碼重現(xiàn)
前幾天有個(gè)學(xué)生小K編寫(xiě)集合代碼時(shí),運(yùn)行的結(jié)果中卻出現(xiàn)了一個(gè)自己沒(méi)見(jiàn)過(guò)的異常,他不知道怎么解決,于是就跑來(lái)找輝哥幫忙。下面就是小K的代碼,大家可以來(lái)看看,如下所示:

上述代碼,一旦運(yùn)行就會(huì)出現(xiàn)下圖中的異常現(xiàn)象。說(shuō)實(shí)話,對(duì)輝哥來(lái)說(shuō),只要一遇到bug,真是瞬間感覺(jué)連吃大盤(pán)雞都不香了,必須立馬盤(pán)它才行。

上圖中,我們看到了一個(gè)叫做ClassCastException類(lèi)型轉(zhuǎn)換的異常!為什么會(huì)出現(xiàn)這個(gè)bug呢?其實(shí)如果我們仔細(xì)檢查一下代碼,就會(huì)發(fā)現(xiàn)原來(lái)是集合中的值寫(xiě)錯(cuò)了!我們聲明的集合泛型是Double類(lèi)型的,結(jié)果添加數(shù)據(jù)元素的時(shí)候,給集合添加了一個(gè)整型的元素,這樣就造成了上述異常。而且根據(jù)錯(cuò)誤信息的提示,異常出現(xiàn)在代碼的第40行位置,現(xiàn)在我們知道了異常的原因和位置,接下來(lái)解決就容易了。
二. bug分析
其實(shí)上述代碼中之所以會(huì)出現(xiàn)問(wèn)題,是因?yàn)榧蠈?duì)泛型的嚴(yán)格要求所導(dǎo)致的。一開(kāi)始小K覺(jué)著int類(lèi)型可以直接轉(zhuǎn)換為double類(lèi)型,所以就往集合中添加了整型數(shù)據(jù)。但實(shí)際上Java中的集合泛型,要求的必須是包裝類(lèi),我們的代碼中就是Interger和Double,所以是無(wú)法將基本類(lèi)型直接轉(zhuǎn)為包裝類(lèi)型的。但小K卻不明白,為什么基本類(lèi)型與包裝類(lèi)型兩者的類(lèi)型不一致,但在往集合中添加數(shù)據(jù)時(shí)卻可以添加進(jìn)去呢?為了給小K講明白這個(gè)問(wèn)題,輝哥就通過(guò)javap命令帶小K查看了反編譯后的List類(lèi)型,我們來(lái)看看泛型的底層究竟是個(gè)什么情況,如下圖所示:

通過(guò)反編譯可以看出,集合在底層編譯時(shí),其實(shí)所謂的泛型都被擦除了。也就是說(shuō),當(dāng)我們?cè)谑褂梅盒蜁r(shí),任何具體的類(lèi)型信息都被擦除了,你唯一知道的就是你在使用一個(gè)對(duì)象。所以List和List在運(yùn)行時(shí)事實(shí)上是相同的類(lèi)型。而這其中原始類(lèi)型的集合是特別容易出問(wèn)題的,因?yàn)樵碱?lèi)型會(huì)跳過(guò)泛型檢查且很不安全,List、List 和 List 等存在著巨大的差異,泛型在使用中很容易造成類(lèi)型擦除。那么到底什么是泛型擦除?我們繼續(xù)往下看。
三. 泛型的擦除
我們知道,Java泛型這個(gè)特性并不是一開(kāi)始就有的,而是從JDK 1.5才開(kāi)始加入的。因此Sun公司為了兼容之前的舊版本,Java對(duì)泛型的實(shí)現(xiàn)采取了“偽泛型”的策略,也就是說(shuō)Java在語(yǔ)法上支持泛型,但在編譯階段會(huì)進(jìn)行所謂的“類(lèi)型擦除”(Type Erasure),將所有的泛型表示(尖括號(hào)中的內(nèi)容)都替換為具體的類(lèi)型(其對(duì)應(yīng)的原生態(tài)類(lèi)型),就像完全沒(méi)有泛型一樣。
并且泛型在擦除的時(shí)候,還會(huì)根據(jù)泛型的具體類(lèi)型來(lái)進(jìn)行。
四. 泛型相關(guān)知識(shí)回顧
泛型其實(shí)就是引用類(lèi)型的占位符,主要用于避免引用類(lèi)型的相互轉(zhuǎn)換,替換之前使用的Object類(lèi)型,去除不同類(lèi)型之間的強(qiáng)轉(zhuǎn)。
1. 泛型的應(yīng)用
泛型主要可以用在 泛型類(lèi)、泛型接口、泛型方法 上,也就是說(shuō),泛型可以在類(lèi)、接口、方法上使用。
2. 泛型通配符
在泛型中,有幾個(gè)常用的通配符,我們需要掌握。
?:表示右邊的泛型可以是任意類(lèi)型,還可以指定一個(gè)泛型的上限和下限。
泛型上限:
- 語(yǔ)法格式: 類(lèi)型名稱(chēng) 對(duì)象名稱(chēng)
- 語(yǔ)法意義: 只能接收該類(lèi)型及其子類(lèi)
泛型下限:
- 語(yǔ)法格式: 類(lèi)型名稱(chēng) 對(duì)象名稱(chēng)
- 語(yǔ)法意義: 只能接收該類(lèi)型及其父類(lèi)型
具體用法,如下圖所示:

現(xiàn)在你知道為什么會(huì)出現(xiàn)上述異常了嗎?對(duì)泛型的理解是否有進(jìn)一步加深了呢?如果還有不明白的地方,可以給客服留言,客服會(huì)及時(shí)給你回復(fù)的。
開(kāi)班時(shí)間:2021-04-12(深圳)
開(kāi)班盛況開(kāi)班時(shí)間:2021-05-17(北京)
開(kāi)班盛況開(kāi)班時(shí)間:2021-03-22(杭州)
開(kāi)班盛況開(kāi)班時(shí)間:2021-04-26(北京)
開(kāi)班盛況開(kāi)班時(shí)間:2021-05-10(北京)
開(kāi)班盛況開(kāi)班時(shí)間:2021-02-22(北京)
開(kāi)班盛況開(kāi)班時(shí)間:2021-07-12(北京)
預(yù)約報(bào)名開(kāi)班時(shí)間:2020-09-21(上海)
開(kāi)班盛況開(kāi)班時(shí)間:2021-07-12(北京)
預(yù)約報(bào)名開(kāi)班時(shí)間:2019-07-22(北京)
開(kāi)班盛況
Copyright 2011-2023 北京千鋒互聯(lián)科技有限公司 .All Right
京ICP備12003911號(hào)-5
京公網(wǎng)安備 11010802035720號(hào)