前言
看了一早上的泛型我很蛋疼,我發(fā)現(xiàn)我之前用泛型一直都是不明不白的。
正文
我相信類似于
List<String> list = new ArrayList<>();
這種類型的泛型使用方法用的很多吧,可光會(huì)用也只能停在最初級(jí)的階段,在開始我今天的表演之前我得說(shuō)Java的泛型其實(shí)是一種偽泛型。好了廢話不多說(shuō)上代碼
1.泛型類
public class GenericClass<T> {
private T t1;
private T t2;
public T getT1() {
return t1;
}
public void setT1(T t1) {
this.t1 = t1;
}
public T getT2() {
return t2;
}
public void setT2(T t2) {
this.t2 = t2;
}
}
為什么這么寫呢?我覺得只是為了代表這個(gè)類的成員變量是相同類型或者成員方法返回類型是相同類型(E(集合元素類型例如List<E>)K和V(關(guān)鍵字和值)T、U、S(代表任意類型))
2.泛型方法
public static <T> T getMiddle(T... a) {
return a[a.length/2];
}
首先設(shè)計(jì)泛型方法的前提是因?yàn)槲覀儾幌氚颜麄€(gè)類型泛型化,而只是因?yàn)檫@個(gè)方法需要泛型的功能而去設(shè)計(jì)的,至于為什么設(shè)計(jì)成靜態(tài)因?yàn)樵诜盒皖惱锩骒o態(tài)方法是無(wú)法得知它具體的類型的,所以說(shuō)是設(shè)計(jì)成這樣,當(dāng)然它可以出現(xiàn)在泛型類還有普通類里面。它的調(diào)用可能是這樣的
GenericClass.<String>getMiddle("1", "2", "3");
其實(shí)<String>
可以省略因?yàn)榫幾g器聰明到你無(wú)法想象的地步。GenericClass.getMiddle("1", "2", "3");
3.類型擦除(發(fā)生在編譯階段,但是還是存有相關(guān)泛型信息)
類型擦除就是我要說(shuō)為什么要說(shuō)它是偽泛型了,為什們要類型擦除了因?yàn)樵贘DK1.0的時(shí)候根本就沒(méi)考慮泛型,所以為了向后兼容只能使用類型擦除這種方式去實(shí)現(xiàn)泛型的功能實(shí)際它是怎么操作的呢?
其實(shí)定義一個(gè)泛型類型的時(shí)候,都自動(dòng)提供一個(gè)相應(yīng)的原始類型(raw type),原始類型就是刪去類型參數(shù)后的泛型類型名。擦除類型變量,并替換為限定類型(無(wú)限定的變量用Object,有多個(gè)限定則是第一個(gè)限定類型)。就拿上面的例子來(lái)說(shuō)
public class GenericClass {
private Object t1;
private Object t2;
public Object getT1() {
return t1;
}
public void setT1(Object t1) {
this.t1 = t1;
}
public Object getT2() {
return t2;
}
public void setT2(Object t2) {
this.t2 = t2;
}
}
假設(shè)我們調(diào)用了getT1方法。
首先肯定是對(duì)原始方法getT1的調(diào)用,然后再?gòu)?qiáng)制轉(zhuǎn)換為T(確定類型)類型。
擦除可能會(huì)遇到一種情況和多態(tài)的沖突
class subGenericClass extends GenericClass<Double> {
private Double t1;
public void setT1(Double t1) {
this.t1 = t1;
}
}
可是類型擦除后是繼承的只有setT1(Object t1)這個(gè)方法的,那么虛擬機(jī)怎么處理這種情況呢。其實(shí)它會(huì)自動(dòng)生成一個(gè)橋方法
public void setT1(Object t1) {
setT1((Double) t1);
}
有空再講講泛型的通配符