4.泛型與虛擬機器
阿新 • • 發佈:2018-12-31
[1]虛擬機器中沒有泛型,只有普通的類和方法
[2]所有的型別引數都用它們的限定型別替換
無論何時定義一個泛型型別,都自動提供了一個相應的原始型別。原始型別的名字就是刪去型別引數後的泛型型別名。擦除型別變數,並替換為限定型別(無限定的變數用 Object)
如Pair的原始型別:
public class Pair {
private Object first;
private Object second;
public Pair(Object first, Object second) {
this.first = first;
this .second = second;
}
}
以上是無限定的情況,接下來是有限定的情況。有限定則原始型別用第一個限定的型別變數來替換:
public class Interval<T extends Comparable & Serializable> {
private T lower;
private T upper;
public Interval(T first,T second) {
...
}
}
它的原始型別為:
public class Interval {
private Comparable lower;
private Comparable upper;
public Interval(Comparable first, Comparable second) {
...
}
}
[3]為保持型別安全性,必要時插入強制型別轉換
如:
Pair<Employee> buddies = ...;
Employee buddy = buddies.getFirst();
編譯器把這個方法的呼叫翻譯為兩條虛擬機器指令:
1.對原始方法Pair.getFirst的呼叫
2.將返回的Object型別強制轉換為Employee型別
[4]橋方法被合成來保持多型
class DateInterval extends Pair<LocalDate> {
public void setSecond(LocalDate second) {
if(second.compareTo(getFirst()>=0)
super.setSecond(second);
}
}
它的原始型別為:
class DateInerval extends Pair {
public void setSecond(LocalDate second) {...}
}
它從Pair中也繼承了一個setSecond方法:
public void setSecond(Object second);
那麼
DateInterval interval = new DateInterval(...);
Pair<localDate>pair = interval;
pair.setSecond(aDate);
此時的呼叫要具有多型性並呼叫最適合的方法,因此,就需要編譯器在DateInterval類中生成一個橋方法:
public void setSecond(Object second) {
setSecond((Date) second);
}
首先,變數pair已經宣告為型別Pair,並且這個型別只有一個簡單的方法叫setSecond,即setSecond(Object)。虛擬機器用pair引用的物件呼叫這個方法。這個物件是DateInterval型別的,因而會呼叫DateInterval.setSecond(Object)方法。這個方法是合成的橋方法,它呼叫DateInterval.setSecond(Date),這正是我們所期望的操作效果。
注:本文為《Java 核心技術 卷I》讀書筆記及個人理解解釋