前面提到過莺戒,Java泛型是1.5才引進(jìn)來的掰烟,不像其他語言天生就支持泛型爽蝴。為了兼容1.5之前的代碼,Java從編譯器動(dòng)手纫骑,使用擦除的手段支持泛型蝎亚,這也使得Java的泛型有局限性。下面講解擦除的原理及其局限性先馆,對(duì)Java泛型有個(gè)全面的了解发框,在使用泛型的時(shí)候不再疑惑。
擦除
List<String> strList = new ArrayList<>();
List<Integer> intList = new ArrayList<>();
System.out.println(strList.getClass().getName()); //java.util.ArrayList
System.out.println(intList.getClass().getName()); //java.util.ArrayList
System.out.println(strList.getClass() == intList.getClass()); //true
可見煤墙,在運(yùn)行時(shí)List<String>與List<Integer>的類型信息是一樣的
class Holder<T>{
private T t;
public Holder(T t){
this.t = t;
}
}
Holder<String> stringHolder = new Holder<>("str");
Holder<Integer> intHolder = new Holder<>(123);
System.out.println(Arrays.toString(stringHolder.getClass().getTypeParameters())); //[T]
System.out.println(Arrays.toString(intHolder.getClass().getTypeParameters())); //[T]
getTypeParameters返回泛型聲明對(duì)應(yīng)的類型參數(shù)梅惯,從打印上看到并不是返回具體的類型,二是返回[T],是一個(gè)占位標(biāo)識(shí)符仿野。
泛型會(huì)擦除掉類型參數(shù)铣减,類里面的聲明會(huì)變成類型邊界(類型邊界后面會(huì)講到),如果沒有聲明類型邊界就是Object脚作。當(dāng)你想使用T的時(shí)候葫哗,不知道它具體的類型,只能當(dāng)做類型邊界的類鳖枕,調(diào)用它的方法魄梯。
擦除只是在使用T的時(shí)候,上面看到stringHolder.get()的時(shí)候編譯器會(huì)自動(dòng)幫我們把返回的參數(shù)轉(zhuǎn)換為String類型
邊界
class Animal{
private String name;
public Animal(String name){
this.name = name;
}
public String getAnimalName() {
return name;
}
}
class Holder<T>{
private T pet;
public Holder(T t){
pet = t;
}
}
class Holder2<T extends Animal>{ //聲明Animal為類型參數(shù)的邊界
private T pet;
public Holder2(T t){
pet = t;
pet.getAnimalName(); //類型擦除到第一邊界宾符,可以有多個(gè)邊界
}
}
Holder2聲明了類型參數(shù)的邊界酿秸,編譯器實(shí)際上會(huì)把類型參數(shù)替換為它的擦除,T就相當(dāng)于Animal魏烫,pet就行可以使用Animal的方法辣苏,相應(yīng)地pet也只能接收Animal或者Animal的子類
Holder2 holder2 = new Holder2<>(new Animal("aaa"));
Holder2 holder3 = new Holder2<>(new Dog("bbb"));
Holder2 holder4 = new Holder2<>(new Object()); //編譯不通過
多邊界
邊界可以定義多個(gè),與集成一樣哄褒,只能定義一個(gè)class的邊界+多個(gè)接口的邊界,并且class必須放在開始
class Animal{
private String name;
public Animal(String name){
this.name = name;
}
public String getAnimalName() {
return name;
}
}
interface Fly{
void fly();
}
interface Run{
void run();
}
class Holder<T extends Animal & Fly & Run>{
}
目錄
學(xué)會(huì)Java泛型系列(零):簡(jiǎn)介及目錄
學(xué)會(huì)Java泛型系列(一):Java泛型
學(xué)會(huì)Java泛型系列(二):泛型定義與使用
學(xué)會(huì)Java泛型系列(三):泛型原理-擦除
學(xué)會(huì)Java泛型系列(四):擦除帶來的問題以及解決辦法
學(xué)會(huì)Java泛型系列(五):限定符
學(xué)會(huì)Java泛型系列(六):總結(jié)
學(xué)會(huì)Java泛型系列(七):常用案例