天天看點

666之Java泛型的思考

近來重溫了一下《Core Java》中的第8章,關于泛型的描述,重拾了一下之前的知識和了解,總結幾點思考和感悟如下:

  • 泛型的聲明

在類或者方法的定義過程中,可以進行泛型的聲明(一般用大寫字母T來表示),以便類或者方法的後續編寫過程中可以使用這個T作為特定類的表示。

  • 泛型在類定義時的聲明

public class Pair<T> {
    private T first;
    private T second;

    public T getFirst(){}
    public T getSecond(){}
    public void setFirst(T first){
        this.first = first;
    }
    public void setSecond(T second){
        this.second = second;
    }
}
           

跟在Pair後在尖括号中的T就是類定義中泛型的聲明。

  • 泛型在方法定義時的聲明

類似的,方法定義過程中也可以進行泛型的聲明,一般是在方法的modifiers後傳回值前。

public class MethodGeneric{
    public static <T> T printAndReturn(T t){
        System.out.println("do nothing then return input parameter.");
        return t;
    }
}
           

值得注意的有2點:

注意點1,泛型類型可以繼承1個類并同時實作若幹個接口,均用關鍵字extends來表示,繼承的父類(僅能繼承1個)必須放在extends後第一位,實作多個接口用&連接配接起來,如下代碼所示:

public class GenericExtends<T extends BaseClass & Comparable & Serializable> {
    //class body
}
           

注意點2,泛型T是一種編譯時的概念,而不是運作時的概念。也就是說在Java虛拟機運作時是沒有泛型的概念的,統一為Object類或者泛型T所繼承的類或者實作的接口(一般替換為聲明時extends後的第一個)。編譯時會在必要的return等地方根據使用泛型時傳入的具體類型做強制類型轉換。

  • 泛型的上界和下界

說到泛型的上界和下界,必須提到通配符(wildcard——”?“)。為了友善說明,我們定義兩個類:父類Father和子類Son,以及泛型類Pair。

public class Pair<T> {
    private T first;
    private T second;

    public T getFirst(){}
    public T getSecond(){}
    public void setFirst(T first){
        this.first = first;
    }
    public void setSecond(T second){
        this.second = second;
    }
}

class Father{}
class Son extends Father{}
           

首先是泛型的上界,例如? extends Father,這裡需要特别注意的是此處是使用泛型時這個具體傳給T的類型必須是Father的子類。使用上界時可以用get方法,而無法使用set方法,這個具體該怎麼了解呢,我們看一下的案例

public static void main(String[] args){
    
    Pair<? extends Father> p = new Pair<>();
    p.getFirst();    //OK
    Son s = p.getFirst();   //Error,T為Fahter的子類,是以getFirst()可能回傳Father或者Son,是以不能用Son來接收,隻能用Father來接收。
    Father f = p.getFirst();    //OK

    p.setFiert(new Father());    
    //Error,因為此時Pair中的類型T是必須是Father的子類,但是并不知道具體是哪一個子類,究竟是Father還是Son,不明确,是以無法傳具體的類型給T。

}