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