在沒有泛型之前,程式設計師必須使用Object編寫適用於多種型別的程式碼。很繁瑣,也不安全。
泛型的引入使Java有了一個很強的型別系統,允許設計者詳細地描述變數和方法的型別要如何變化。
在普通的情況下,實現泛型程式碼很容易。在更高階的情況下,我們的目標是提供讓其他程式設計師可以輕鬆使用的類和方法,這對實現者來說會非常複雜。
用泛型編寫的程式碼可以對多種不同物件的型別進行重用。
沒有泛型之前,使用Object(繼承)實現不同型別物件間的匹配。這種方法有兩個弊端
因此,泛型提供了一種解決方案:型別引數(type parameter)。
編譯器也可以充分利用這個型別資訊。呼叫get的時候不需要強制轉換。編譯器還知道add方法有一個型別為String的型別引數,這比Object型別要安全。現在,編譯器可以檢查,防止你插入錯誤型別的物件。編譯期出現錯誤比執行期出現類的強制轉換異常要好的多。
有一個或多個型別變數的類。
例如:定義一個型別變數T,用 <>
括起來,放在類名後邊。泛型類還可以有多個型別變數,<T, U>。
變數型別可以應用於方法的返回值型別以及欄位和區域性變數。
使用具體的型別替換型別變數來範例化反省型別,可以把結果想像成一個普通類。
泛型方法可以定義在普通類中,也可以定義在泛型類中。
注意,泛型變數要放在方法返回值前。
呼叫泛型方法的方式(例子是呼叫靜態方法):
場景:某個方法引數為泛型T,在方法體中要呼叫compareTo方法來比較大小,既然使用了泛型,說明該方法可以傳入任何引數物件,那麼如何知道T所屬的類有一個compareTo方法呢?
解決這個問題的方法就是限制T只能是實現了Comparable介面的類。可以通過對變數型別T設定一個限定來實現這一點:public static <T extends Comparable> T min(T[] t)
此時,在呼叫泛型方法min時只能傳遞實現了Comparable介面的型別物件的引數。
語法就是:<T extends BoundingType>,T和限定類可以是類也可以是介面。
一個型別變數或萬用字元可以有多個限定:
注意: 可以限定多個介面,類最多隻能限定一個。如果有一個類作為限定,這個類必須是第一個限定。
無論何時定義一個泛型,都會自動提供一個原始型別(raw type)。這個原始型別就是去掉型別引數後的泛型型別名。對於無限定的變數替換為Object。
原始型別第一個限定型別來替換型別變數,如果沒有給定限定,則替換為Object。例如:
public class Interval<T extends Comparable & Serializable> {
private T lower;
}
// Comparable為第一個限定型別,所以使用它來替換
public class Interval {
private Comparable lower;
}
這個註解會關閉程式碼檢查
泛型萬用字元搭配集合使用一般在方法的引數中比較常見
方法中的引數是一個集合,集合如果攜帶了萬用字元,要特別注意如下:
1 集合的型別會提升為Object型別。
2 方法中的引數是一個集合,集合如果攜帶了萬用字元,那麼此集合不能進行新增和修改操作 , 可以刪除和獲取
在集合中泛型是不支援多型的,如果為了匹配任意型別,我們就會使用泛型萬用字元了。
<?>
可以表示任意型別
對泛型做約束,給泛型指定型別時,只能是某個類的父類別或子類。
visualgo.net