1、定義:泛型的本質是參數化類型,就是將類型由原來的具體的類型參數化,這種參數類型可以用在類、接口、方法中,分別稱為泛型類、泛型接口、泛型方法;
2、泛型類:泛型類的聲明和非泛型類的聲明類似,除了在類名后面添加了類型參數聲明部分,最典型的就是各種容器類,List、Set、Map;
public class Test<T>{ private T t; public T getT() { return t; } public void setT(T t) { this.t = t; } }
a、泛型的類型參數只能是引用型類型<Integer>、<Double>(包括自定義類)等,不能是原始類型<int>、<double>等;
b、實例化泛型類時,必須指定 T 的具體類型;
c、參數化類型 T 可以寫成任意字符,常用的 T 、E、K、V等表示泛型;
3、泛型接口:泛型接口與泛型類的定義及使用基本相同;
a、實現泛型接口的類未傳入泛型實參時,在聲明此類的時候,需將泛型的聲明也加到類中;
class B<T> implements Test<T>{ @Override public T next() { return null; }
b、實現泛型接口的類傳入泛型實參時,需將所有使用泛型的地方都要換成實參類型;
public class B implements Test<String> { private String[] strs= new String[]{"a", "b", "c"}; @Override public String next() { return null; } }
4、泛型方法:調用方法的時候,指明泛型的具體類型;
// 泛型類 class Box<T> { /** * 在泛型類中聲明了一個泛型方法,使用泛型E,這種泛型E可以為任意類型,可以類型與T相同,也可以不同。 * 由於泛型方法在聲明的時候會聲明泛型<E>,因此即使在泛型類中並未聲明泛型,編譯器也能夠正確識別泛型方法中識別的泛型。 */ public <E> void B_1(E t) { System.out.println(t.toString()); } /** * 在泛型類中聲明了一個泛型方法,使用泛型T,注意這個T是一種全新的類型,可以與泛型類中聲明的T不是同一種類型。 * */ public <T> void B_2(T t) { System.out.println(t.toString()); } // 不是泛型方法 public void B_3(T t){ System.out.println(t.toString()); } }
a、所有泛型方法聲明都有一個類型參數聲明部分(由尖括號分隔),該類型參數聲明部分在方法返回類型之前(在上面例子中的<E>、<T>);
b、只有聲明了<T>、<E>的方法才是泛型方法(B_1、B_2),泛型類中使用泛型的成員方法不是泛型方法(B_3);
c、<T>、<E>表明該方法將使用泛型類型T、E,此時才可以在方法中使用泛型類型T、E;
d、泛型方法體的聲明和其他方法一樣,只能是引用型類型,不能是原始類型(int、double,char等);
5、泛型上下邊界:在使用泛型的時候,我們還可以為傳入的泛型類型實參進行上下邊界的限制,類型實參只准傳入某種類型的父類或某種類型的子類;為泛型添加上邊界,即傳入的類型實參必須是指定類型的子類型;比如:
List<? extends Animal>, 通配符的上限,不能往里存,只能往外取,因為編譯器只知道容器里的是父類或者父類的子類,但不知道它具體是什么類型,所以存的時候,無法判斷是否要存入的數據的類型與容器種的類型一致,所以會拒絕set操作
<? super E>通配符的下限,往外取只能賦值給Object變量,不影響往里存,因為編譯器只知道它是子類或者它的父類,這樣實際上是放松了類型限制,父類一直到Object類型的對象都可以往里存,但是取的時候,就只能當成Object對象使用了
// 泛型類 class Box<T extends Number> { private T t; public Box(T t){ this.t = t; } public T getT(){ return t; } }
// Integer類型是Number類型的子類————正確
Box<Integer> b = new Box<Integer>(1000);
// String類型不是Number類型的子類————錯誤
Box<String> s = new Box<String>("1000");
6、類型通配符:一般是使用 ?代替具體的類型參數,?是類型實參,和Integer、Number一樣都是一種實際的類型,?可以看成所有的類型的父類(List<?> 在邏輯上是List<String>,List<Integer> 等所有List<具體類型實參>的父類);
public static void main(String[] args) { Box b = new Box(); List<String> sLst = new ArrayList<String>(); sLst.add("100"); List<Integer> iLst = new ArrayList<Integer>(); iLst.add(100); List<Number> nLst = new ArrayList<Number>(); nLst.add(1000); b.BPrint(sLst); b.BPrint(iLst); b.BPrint(nLst); } /** * <? extends T>表示該通配符所代表的類型是T類型的子類 * <? super T>表示該通配符所代表的類型是T類型的父類 */ class Box { public void BPrint(List<?> lst) { System.out.println(lst); } }
