1. 程式人生 > >4.泛型與虛擬機器

4.泛型與虛擬機器

[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》讀書筆記及個人理解解釋