java泛型

泛型類

一個泛型類 (generic class) 就是具有一個或多個類型變量的類。

  • 泛型類可以有多個類型變量。 例如 , 可以定義 Pair 類 , 其中第一個域和第二個域使用不同的類型,類定義中的類型變量指定方法的返回類型以及域和局部變量的類型。
public class a<T,U>{}

泛型方法

當(dāng)某個類只有一個方法需要使用泛型時,可不必將整個類聲明為泛型類,可以單獨(dú)聲明泛型方法。

  • 泛型方法可以定義在普通類中, 也可以定義在泛型類中。
  • 當(dāng)調(diào)用一個泛型方法時,在方法名前的尖括號中放人具體的類型。
public class ArrayAlg{
    public static <T> T getMiddle(T... a){
        return a[a.length / 2];
    }
}
String middle = ArrayAlg.<String>getMiddle("a","b","c");
//等同于,編譯器有足夠的信息能夠推斷出所調(diào)用的方法
String middle = ArrayAlg.getMiddle("a","b","c")

類型變量的限定

限定表示對變量進(jìn)行進(jìn)一步限制,必須繼承自某類或者實(shí)現(xiàn)某接口。

  • <T extends BoundingType〉示 T 應(yīng)該是綁定類型的子類型 (subtype) 。T 和綁定類型可以是類, 也可以是接口 。 選擇關(guān)鍵字 extends 的原因是更接近子類的概念。
  • 一個類型變量或通配符可以有多個限定,限定類型用 “ & ” 分隔, 而逗號用來分隔類型變量,有個限定多個接口,但同時只能限定一個類,如果包含類時,需要將類作為第一位。
public static <A extends Comparable,B extends Comparable> void test(A a,B b){}

類型擦除

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

public class A<T>{
    private T a;
    private T b;
}
//由于T是“無限定變量”擦除后將轉(zhuǎn)變成原始類型(Object)
public class B{
    private Object a;
    private Object b;
}
  • 原始類型用第一個限定的類型變量來替換 , 如果沒有給定限定就用 Object 替換。
public class A<T extends Comparable & Serializable> implements Serializable{
    private T a; 
    private T b;
}
//將轉(zhuǎn)化為
public class A implements Serializable{
    private Comparable a; 
    private Comparable b;
}
  • 當(dāng)程序調(diào)用泛型方法時, 如果擦除返回類型 ,編譯器插入強(qiáng)制類型轉(zhuǎn)換。
Pair<Employee> buddies = ...;
Employee buddy = buddies.getFirst();
//編譯器把這個方法調(diào)用翻譯為兩條虛擬機(jī)指令
//對原始方法 Pair.getFirst()的調(diào)用,此時泛型方法將返回Object
//將返回的Object類型強(qiáng)制轉(zhuǎn)換為Employee類型。
  • 虛擬機(jī)對當(dāng)get或set一個泛型字段時也會插人強(qiáng)制類型轉(zhuǎn)換。

  • 橋方法

    在繼承泛型類型的時候,橋方法的合成是為了避免類型變量擦除所帶來的多態(tài)災(zāi)難。

public class a<T>{
    private T name;
    public void setName(T name){}
    public T getName(){}
}
//類型擦除后轉(zhuǎn)變?yōu)?public class a{
    private Object name;
    public void setName(Object name){}
    public Object getName(){}
}

public class b extends a<String>{
    public void setName(String name){}
    public String getName(){}
}
//類型擦除后轉(zhuǎn)變?yōu)?重載了setName方法而不是重寫
public class b extends a{
    public void setName(String name){}
    //編譯器會生成一個橋方法來實(shí)現(xiàn)多態(tài)
    public void setName(Object name){
        setName(String(name));
    }
    //編譯器會生成一個橋方法實(shí)現(xiàn)對getName的覆蓋
    public Object getName(){
        return String(this.name);
    }
}

  • 虛擬機(jī)中沒有泛型 , 只有普通的類和方法 。
    所有的類型參數(shù)都用它們的限定類型替換 。
    橋方法被合成來保持多態(tài) 。
    為保持類型安全性 , 必要時插人強(qiáng)制類型轉(zhuǎn)換
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 泛型的好處 使用泛型的好處我覺得有兩點(diǎn):1:類型安全 2:減少類型強(qiáng)轉(zhuǎn) 下面通過一個例子說明: 假設(shè)有一個Tes...
    德彪閱讀 1,216評論 0 0
  • 前面,由于對泛型擦除的思考,引出了對Java-Type體系的學(xué)習(xí)。本篇,就讓我們繼續(xù)對“泛型”進(jìn)行研究: JDK1...
    賈博巖閱讀 5,300評論 3 29
  • 開發(fā)人員在使用泛型的時候,很容易根據(jù)自己的直覺而犯一些錯誤。比如一個方法如果接收List作為形式參數(shù),那么如果嘗試...
    時待吾閱讀 1,127評論 0 3
  • 對于我們java中的泛型,可能很多人知道怎么使用并且使用的還不錯,但是我認(rèn)為想要恰到好處的使用泛型,還是需要深入的...
    Single_YAM閱讀 607評論 0 5
  • 想把心里的話我說出去,又不斷想隱藏自己。
    銀色的你閱讀 174評論 0 0

友情鏈接更多精彩內(nèi)容