2018-06-02 8.5 虛擬機(jī)對泛型代碼的處理

以下部分只是將我在學(xué)習(xí)筆記中的關(guān)于Java核心技術(shù)卷一 8.5 的筆記單拆出來凡恍,形成一篇文章山林。

8.5 泛型代碼和虛擬機(jī)

1.無論何時(shí)定義一個(gè)泛型類型房待,都自動提供了一個(gè)相應(yīng)的原始類型(raw type)。原始類型的名字就是刪去類型參數(shù)后的泛型類型名。擦除(erased) 類型變量, 并替換為限定類型(無限定的變量用 Object)桑孩。

2.java中的泛型只在程序源碼中存在拜鹤,當(dāng)編譯成字節(jié)碼之后,就會變?yōu)樵碱愋土鹘罚琷ava實(shí)現(xiàn)泛型的方法是類型擦除署惯。

3.當(dāng)程序調(diào)用泛型方法時(shí),如果擦除返回類型镣隶, 編譯器插入強(qiáng)制類型轉(zhuǎn)換极谊。例如,下面這個(gè)語句序列

Pair buddies = . .

Employee buddy = buddies.getFirst()安岂;

擦除

getFirst 的返回類型后將返回 Object 類型轻猖。編譯器自動插人 Employee

的強(qiáng)制類型轉(zhuǎn)換,將返回的Object類型轉(zhuǎn)換為Employee類型域那。當(dāng)存取一個(gè)泛型域時(shí)也要插入強(qiáng)制類型轉(zhuǎn)換咙边。假設(shè) Pair 類的 first

域和 second 域都是公 有的。表達(dá)式:

Employee buddy = buddies.first;

就會在結(jié)果字節(jié)碼中插入強(qiáng)制類型轉(zhuǎn)換次员。

4.類型擦除也會出現(xiàn)在泛型方法中败许,由此產(chǎn)生一些問題:在一個(gè)子類中,如果對于父類的一個(gè)函數(shù)進(jìn)性了重載淑蔚,則在擦除之后就會破壞重載市殷。比如說:

class Datelnterval extends Pair

{

????public void setSecond(LocalDate second)

????{

????????if (second.compareTo(getFirstO) >= 0)

??????? super.setSecond(second);

????}

}

在被擦除之后,就會變?yōu)椋?/p>

class Datelnterval extends Pair

{

????public void setSecond(LocalDate second)

??? {……}

}

而在父類中刹衫,則有一個(gè)public

void setSecond(Object second)方法醋寝,原本這個(gè)方法應(yīng)該作為模板方法被實(shí)例化為public void

setSecond(LocalDate

second)而后被子類中的同名方法所重載,但是此時(shí)由于擦除带迟,重載被破壞了音羞,父類的方法與子類中的這個(gè)方法變?yōu)榱藘蓚€(gè)方法,public void

setSecond(Object second)和public void setSecond(LocalDate

second)共同出現(xiàn)在子類中仓犬。

因此嗅绰,編譯器的解決方法是在作為子類的Datelnterval類中,生成一個(gè)橋方法搀继,即為:

public

void setSecond(Object second) { setSecond((Date) second);

}窘面,這個(gè)方法使用了與父類方法在擦除之后相同的函數(shù)名,返回值律歼,與參數(shù)列表民镜,從而完全將父類方法覆蓋啡专,而這個(gè)橋方法的作用則是险毁,將變量強(qiáng)制類型轉(zhuǎn)換之后,傳入子類方法,而在實(shí)際使用時(shí)畔况,如果一個(gè)Pair的引用引用了一個(gè)Datelnterval類的變量鲸鹦,在接收參數(shù)時(shí),即使調(diào)用橋函數(shù)跷跪,也會和以前一樣運(yùn)行馋嗜。

5.假設(shè)Datelnterval類也重載了getSecond()方法,比如說:

class Datelnterval extends Pair

{

??? public LocalDate getSecond()

??? {

???? return (Date) super.getSecond().clone();

????}

????……

}

那么吵瞻,在擦除之后葛菇,這個(gè)類中就會有兩個(gè)函數(shù):

public LocalDate getSecond()

public Object getSecond()/*這是一個(gè)橋方法,它將Pair類中的方法給覆蓋掉了*/

由于虛擬機(jī)中橡羞,是使用參數(shù)類型和返回類型唯一確定一個(gè)方法眯停,因此雖然在源碼中無法寫出如此形式,但是在最后生成的字節(jié)碼中卿泽,卻會出現(xiàn)以上這種情況莺债。

6.這也導(dǎo)致了其他問題,比如說:

public class TestTheBug

{

public static void method (Pair pairex)? {? ? ? ? System.out.println("Pair string pairex");? ? }

public static void method (Pair pairex)? {? ? ? ? System.out.println("Pair int pairex");? ? }

}

這段代碼表面上沒有問題签夭,但事實(shí)上是無法進(jìn)行編譯的齐邦,因?yàn)樵谶M(jìn)性擦除之后,這兩個(gè)函數(shù)的函數(shù)頭部已經(jīng)完全一致了第租,由此造成錯(cuò)誤措拇。但是,如果你進(jìn)行這樣的修改:

public class TestTheBug

{

public static string method (Pair pairex)

{

System.out.println("Pair string pairex");

? ? return "? "

??? }

public static int method (Pair pairex)

{

System.out.println("Pair int pairex");

??? return 1;

??? }

}

這兩個(gè)方法就可以照常運(yùn)行慎宾,因?yàn)橥ㄟ^不同的參數(shù)列表儡羔,通過了編譯器,而后又通過不同的返回值璧诵,使得虛擬機(jī)也可以區(qū)分汰蜘。

7.橋方法不僅用于泛型類型。 在一個(gè)方法覆蓋另一個(gè)方法時(shí)可以指定一個(gè)更嚴(yán)格的返回類型之宿。例如:

public class Employee implements Cloneable

??? {

??????? public Employee clone() throws CloneNotSupportedException { ...}

??? }

Object.clone 和 Employee.clone 方法被說成具有協(xié)變的返回類型(covariant returntypes)族操。 實(shí)際上,Employee 類有兩個(gè)克隆方法:

Employee clone() // defined above

Object clone() // 合成的橋方法比被,覆蓋了原本的Object.clone方法

合成的橋方法中調(diào)用了新定義的方法色难。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市等缀,隨后出現(xiàn)的幾起案子枷莉,更是在濱河造成了極大的恐慌,老刑警劉巖尺迂,帶你破解...
    沈念sama閱讀 222,378評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笤妙,死亡現(xiàn)場離奇詭異冒掌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蹲盘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評論 3 399
  • 文/潘曉璐 我一進(jìn)店門股毫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人召衔,你說我怎么就攤上這事铃诬。” “怎么了苍凛?”我有些...
    開封第一講書人閱讀 168,983評論 0 362
  • 文/不壞的土叔 我叫張陵趣席,是天一觀的道長。 經(jīng)常有香客問我醇蝴,道長吩坝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,938評論 1 299
  • 正文 為了忘掉前任哑蔫,我火速辦了婚禮钉寝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘闸迷。我一直安慰自己嵌纲,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評論 6 398
  • 文/花漫 我一把揭開白布腥沽。 她就那樣靜靜地躺著逮走,像睡著了一般。 火紅的嫁衣襯著肌膚如雪今阳。 梳的紋絲不亂的頭發(fā)上师溅,一...
    開封第一講書人閱讀 52,549評論 1 312
  • 那天,我揣著相機(jī)與錄音盾舌,去河邊找鬼墓臭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛妖谴,可吹牛的內(nèi)容都是我干的窿锉。 我是一名探鬼主播,決...
    沈念sama閱讀 41,063評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼膝舅,長吁一口氣:“原來是場噩夢啊……” “哼嗡载!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起仍稀,我...
    開封第一講書人閱讀 39,991評論 0 277
  • 序言:老撾萬榮一對情侶失蹤洼滚,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后技潘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體遥巴,經(jīng)...
    沈念sama閱讀 46,522評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡千康,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了挪哄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吧秕。...
    茶點(diǎn)故事閱讀 40,742評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡琉闪,死狀恐怖迹炼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情颠毙,我是刑警寧澤斯入,帶...
    沈念sama閱讀 36,413評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站蛀蜜,受9級特大地震影響刻两,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜滴某,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評論 3 335
  • 文/蒙蒙 一磅摹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧霎奢,春花似錦户誓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至晤硕,卻和暖如春悼潭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背舞箍。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評論 1 274
  • 我被黑心中介騙來泰國打工舰褪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人疏橄。 一個(gè)月前我還...
    沈念sama閱讀 49,159評論 3 378
  • 正文 我出身青樓抵知,卻偏偏與公主長得像,于是被迫代替她去往敵國和親软族。 傳聞我的和親對象是個(gè)殘疾皇子刷喜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 使用教材:java核心技術(shù) 卷一 第十版 8.1 1.在 Java 中增加范型類之前, 泛型程序設(shè)計(jì)是用繼承實(shí)現(xiàn)的...
    靜者達(dá)觀閱讀 295評論 1 1
  • 引言:泛型一直是困擾自己的一個(gè)難題立砸,但是泛型有時(shí)一個(gè)面試時(shí)老生常談的問題掖疮;今天作者就通過查閱相關(guān)資料簡單談?wù)勛约簩?..
    cp_insist閱讀 1,850評論 0 4
  • 5繼承 5.1 類、超類和子類 重用部分代碼颗祝,并保留所有域浊闪∧詹迹“is-a”關(guān)系,用extends表示搁宾。 已存在的類被...
    我快要上天啦閱讀 788評論 1 3
  • 對象的創(chuàng)建與銷毀 Item 1: 使用static工廠方法折汞,而不是構(gòu)造函數(shù)創(chuàng)建對象:僅僅是創(chuàng)建對象的方法,并非Fa...
    孫小磊閱讀 1,996評論 0 3
  • 今天在超市發(fā)現(xiàn)了一種新的菌菇盖腿,名字叫豬肚菇爽待,我當(dāng)機(jī)立斷買下來,晚上回家做碗菌菇湯面翩腐,味道鮮美鸟款,即使一碗面也要精工細(xì)...
    阿紫lisa閱讀 292評論 0 0