泛型類(lèi)
一個(gè)泛型類(lèi) (generic class) 就是具有一個(gè)或多個(gè)類(lèi)型變量的類(lèi)。
- 泛型類(lèi)可以有多個(gè)類(lèi)型變量。 例如 忆家, 可以定義 Pair 類(lèi) 犹菇, 其中第一個(gè)域和第二個(gè)域使用不同的類(lèi)型,類(lèi)定義中的類(lèi)型變量指定方法的返回類(lèi)型以及域和局部變量的類(lèi)型。
public class a<T,U>{}
泛型方法
當(dāng)某個(gè)類(lèi)只有一個(gè)方法需要使用泛型時(shí)芽卿,可不必將整個(gè)類(lèi)聲明為泛型類(lèi)揭芍,可以單獨(dú)聲明泛型方法。
- 泛型方法可以定義在普通類(lèi)中卸例, 也可以定義在泛型類(lèi)中称杨。
- 當(dāng)調(diào)用一個(gè)泛型方法時(shí),在方法名前的尖括號(hào)中放人具體的類(lèi)型筷转。
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")
類(lèi)型變量的限定
限定表示對(duì)變量進(jìn)行進(jìn)一步限制,必須繼承自某類(lèi)或者實(shí)現(xiàn)某接口呜舒。
- <T extends BoundingType〉示 T 應(yīng)該是綁定類(lèi)型的子類(lèi)型 (subtype) 锭汛。T 和綁定類(lèi)型可以是類(lèi), 也可以是接口 袭蝗。 選擇關(guān)鍵字 extends 的原因是更接近子類(lèi)的概念唤殴。
- 一個(gè)類(lèi)型變量或通配符可以有多個(gè)限定,限定類(lèi)型用 “ & ” 分隔呻袭, 而逗號(hào)用來(lái)分隔類(lèi)型變量眨八,有個(gè)限定多個(gè)接口,但同時(shí)只能限定一個(gè)類(lèi)左电,如果包含類(lèi)時(shí)廉侧,需要將類(lèi)作為第一位。
public static <A extends Comparable,B extends Comparable> void test(A a,B b){}
類(lèi)型擦除
無(wú)論何時(shí)定義一個(gè)泛型類(lèi)型篓足,都自動(dòng)提供了一個(gè)相應(yīng)的原始類(lèi)型(raw type) 段誊。原始類(lèi)型的名字就是刪去類(lèi)型參數(shù)后的泛型類(lèi)型名。 擦除類(lèi)型變M , 并替換為限定類(lèi)型(無(wú)限定的變量用Object)栈拖。
public class A<T>{
private T a;
private T b;
}
//由于T是“無(wú)限定變量”擦除后將轉(zhuǎn)變成原始類(lèi)型(Object)
public class B{
private Object a;
private Object b;
}
- 原始類(lèi)型用第一個(gè)限定的類(lèi)型變量來(lái)替換 连舍, 如果沒(méi)有給定限定就用 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)用泛型方法時(shí)涩哟, 如果擦除返回類(lèi)型 索赏,編譯器插入強(qiáng)制類(lèi)型轉(zhuǎn)換。
Pair<Employee> buddies = ...;
Employee buddy = buddies.getFirst()贴彼;
//編譯器把這個(gè)方法調(diào)用翻譯為兩條虛擬機(jī)指令
//對(duì)原始方法 Pair.getFirst()的調(diào)用,此時(shí)泛型方法將返回Object
//將返回的Object類(lèi)型強(qiáng)制轉(zhuǎn)換為Employee類(lèi)型潜腻。
虛擬機(jī)對(duì)當(dāng)get或set一個(gè)泛型字段時(shí)也會(huì)插人強(qiáng)制類(lèi)型轉(zhuǎn)換。
-
橋方法
在繼承泛型類(lèi)型的時(shí)候器仗,橋方法的合成是為了避免類(lèi)型變量擦除所帶來(lái)的多態(tài)災(zāi)難融涣。
public class a<T>{
private T name;
public void setName(T name){}
public T getName(){}
}
//類(lèi)型擦除后轉(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(){}
}
//類(lèi)型擦除后轉(zhuǎn)變?yōu)?重載了setName方法而不是重寫(xiě)
public class b extends a{
public void setName(String name){}
//編譯器會(huì)生成一個(gè)橋方法來(lái)實(shí)現(xiàn)多態(tài)
public void setName(Object name){
setName(String(name));
}
//編譯器會(huì)生成一個(gè)橋方法實(shí)現(xiàn)對(duì)getName的覆蓋
public Object getName(){
return String(this.name);
}
}
-
虛擬機(jī)中沒(méi)有泛型 童番, 只有普通的類(lèi)和方法 。
所有的類(lèi)型參數(shù)都用它們的限定類(lèi)型替換 威鹿。
橋方法被合成來(lái)保持多態(tài) 剃斧。
為保持類(lèi)型安全性 , 必要時(shí)插人強(qiáng)制類(lèi)型轉(zhuǎn)換