java泛型程序设计——翻译泛型表达式+翻译泛型方法
【0】README
0.1) 本文描述+源代碼均 轉(zhuǎn)自 core java volume 1, 旨在理解 java泛型程序設(shè)計(jì) 的 翻譯泛型表達(dá)式+翻譯泛型方法 的知識(shí);
【1】翻譯泛型表達(dá)式
1.1)當(dāng)程序調(diào)用泛型方法時(shí), 如果擦除了泛型返回類型, 編譯器插入類型轉(zhuǎn)換;
- 1.1.1)看個(gè)荔枝:
- 擦除getFirst的返回類型后將返回Object類型。 編譯器自動(dòng)插入 Employee 的強(qiáng)制類型轉(zhuǎn)換。
- 也就是說(shuō), 編譯器吧這個(gè)方法調(diào)用翻譯為兩條虛擬機(jī)指令(Commands):
- C1)對(duì)原始方法 Pair.getFirst 的調(diào)用;
- C2)將返回的Object類型 強(qiáng)制轉(zhuǎn)換為 Employee 類型;
1.2)當(dāng)存取一個(gè)泛型域時(shí)也要插入強(qiáng)制類型轉(zhuǎn)換。
- 1.2.1)假設(shè) Pair 類的first 域 和 second 域都是 公有的(這不是種好的編程風(fēng)格, 但在java語(yǔ)法中,這是合法的)。
表達(dá)式: Employee buddy = buddies.first; 也會(huì)在結(jié)果字節(jié)碼中插入強(qiáng)制類型轉(zhuǎn)換;
【2】翻譯泛型方法
2.1)類型擦除也會(huì)出現(xiàn)在泛型方法中。
public static <T extends Comparable> T min(T[] a):是一個(gè)完整的方法族;- 2.1.1)擦除類型后, 只剩下一個(gè)方法:
- 注意, 類型參數(shù)T 已經(jīng)被擦除了, 只留下了限定類型 Comparable;
2.2)方法擦除帶來(lái)了兩個(gè)復(fù)雜問(wèn)題。
- 2.2.1)看個(gè)荔枝:
對(duì)以上代碼的分析(Analysis):
- A1)上述類的類型變量擦除后, 為
- A2)令人感到奇怪的是, 存在另一個(gè)從Pair 繼承的setSecond方法, 即
- Attention)此時(shí)要注意, DateInterval內(nèi)部應(yīng)該是重寫了 Pair的 setSecond方法, 結(jié)果擦除類型參數(shù)后, 就不是重寫了, 破壞了類的多態(tài)性;
A3)它們顯然不是同一種方法, 因?yàn)橛胁煌念愋蛥?shù), 一個(gè)是Object , 而另一個(gè)是 Date;(這里是干貨)
A4)然而不應(yīng)該不一樣, 考慮下面的語(yǔ)句序列:
- A5)這里, 希望對(duì)setSecond 的調(diào)用 具有多態(tài)性, 并調(diào)用最合適的那個(gè)方法。 由于pair 引用DateInterval 對(duì)象,所以應(yīng)該調(diào)用 DateInterval.setSecond;
- A6)出現(xiàn)的問(wèn)題:在于類型擦除與多態(tài)發(fā)生了沖突, 確實(shí), 如上面的Attention所說(shuō), 變量類型擦除破壞了類的多態(tài)性;
- A7)解決方法: 就需要編譯器在 DateInterval 類中生成一個(gè)橋方法(bridge method):
2.3)上述引入了橋方法:要想了解他的工作過(guò)程, 跟蹤下列語(yǔ)句 pair.setSecond(aDate);
- 2.3.1)變量pair 已經(jīng)說(shuō)明為類型 Pair , 并且這個(gè)類型只有一個(gè)簡(jiǎn)單的方法叫做 setSecond, 即 setSecond(Object);
- 2.3.2)虛擬機(jī)用 pair 引用的對(duì)象調(diào)用這個(gè)方法: 這個(gè)對(duì)象是 DateInterval 類型的, 因而將會(huì)調(diào)用 DateInterval.setSecond(Object) 方法;
- 2.3.3)這個(gè)方法是合成的橋方法: 它調(diào)用 DateInterval.setSecond(Date)方法,在正是我們想要的;
2.4)橋方法也可以變得很奇怪, 如 DateInterval 方法覆蓋了 getSecond()方法:
class DateInterval extends Pair<ate> {public Date getSecond() {return (Date) super.getSecond().clone();} }對(duì)以上代碼的分析(Analysis):
- A1)在擦除的過(guò)程中, 有兩個(gè)getSecond方法:
- A1.1) Date getSecond() // defined in DateInterval
- A1.2) Object getSecond() // overrides the method defined in Pair to call the first method
- A2)不能這樣編寫代碼(因?yàn)榫哂邢嗤瑓?shù)的兩個(gè)方法是不合法的, 他們都沒(méi)有參數(shù))。
A3)但在虛擬機(jī)中, 用參數(shù)類型和返回類型確定一個(gè)方法, 因此, 編譯器可能產(chǎn)生兩個(gè)僅返回 類型不同的 方法字節(jié)碼, 虛擬機(jī)能夠正確處理這個(gè)情況;
Annotation)A1)橋方法不僅用于泛型類型; 還有, 在一個(gè)方法覆蓋另一個(gè)方法時(shí)可以指定一個(gè)更嚴(yán)格的返回類型:
對(duì)以上代碼的分析(Analysis):
- A1) Object.clone 和 Employee.clone 方法被說(shuō)成具有協(xié)變的返回類型;(具有協(xié)變的返回類型)
- A2)實(shí)際上, Employee 類有兩個(gè)克隆方法(Methods):
- M1) Employee clone();// defined above
- M2) Object clone() ; // synthesized bridge method, overrides Object.clone;
- A3)合成的橋方法調(diào)用了新定義的方法;
Conclusion)總之, 需要記住有關(guān)java泛型轉(zhuǎn)換的事實(shí):
- C1)虛擬機(jī)中沒(méi)有泛型, 只有普通的類和方法;
- C2)所有的類型參數(shù)都是用它們的限定類型替換;
- C3)橋方法被合成來(lái)保持多態(tài);
- C4)為保持類型安全性, 必要時(shí)插入強(qiáng)制類型轉(zhuǎn)換;
總結(jié)
以上是生活随笔為你收集整理的java泛型程序设计——翻译泛型表达式+翻译泛型方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 安卓电玩游戏(安卓电游戏)
- 下一篇: java泛型程序设计——调用遗留代码