java 自定義泛型總結
阿新 • • 發佈:2018-11-07
1、泛型
泛型就是引數化型別
- 適用於多種資料型別執行相同的程式碼
- 泛型中的型別在使用時指定
- 泛型歸根到底就是“模版”
優點:使用泛型時,在實際使用之前型別就已經確定了,不需要強制型別轉換。
2、泛型類使用
泛型有三種使用方式,分別為:泛型類、泛型介面、泛型方法
2.1泛型類
- 只能用在成員變數上,只能使用引用型別
- 泛型型別用於類的定義中,被稱為泛型類。通過泛型可以完成對一組類的操作對外開放相同的介面。最典型的就是各種容器類,如:List、Set、Map。
//此處T可以隨便寫為任意標識,常見的如T、E、K、V等形式的引數常用於表示泛型 //在例項化泛型類時,必須指定T的具體型別 public class test<T>{ //key這個成員變數的型別為T,T的型別由外部指定 private T key; public test(T key) { //泛型構造方法形參key的型別也為T,T的型別由外部指定 this.key = key; } public T getKey(){ //泛型方法getKey的返回值型別為T,T的型別由外部指定 return key; } }
泛型類
2.2泛型介面
- 只能用在抽象方法上
/** * 自定義泛型介面 * * 介面中泛型字母只能使用在方法中,不能使用在全域性常量中 * * @param <T> */ public interface Comparator<T1,T2> { //public static final T1 MAX_VALUE = 100; //介面中泛型字母不能使用在全域性常量中 //T1 MAX_VALUE; public static final int MAX_VALUE = 100; void compare(T2 t); T2 compare(); public abstract T1 compare2(T2 t); }
2.3泛型方法
在其返回值前加<T>
import java.io.Closeable; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.List; /** * 非泛型類中定義泛型方法 * */ public class Method { // 泛型方法,在返回型別前面使用泛型字母 public static <T> void test1(T t){ System.out.println(t); } // T 只能是list 或者list 的子類 public static <T extends List> void test2(T t){ t.add("aa"); } // T... 可變引數 ---> T[] public static <T extends Closeable> void test3(T...a) { for (T temp : a) { try { if (null != temp) { temp.close(); } } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) throws FileNotFoundException { test1("java 是門好語言"); test3(new FileInputStream("a.txt")); } }
2.4 泛型的基本用法
public class GenericTest {
//這個類是個泛型類,在上面已經介紹過
public class Generic<T>{
private T key;
public Generic(T key) {
this.key = key;
}
//我想說的其實是這個,雖然在方法中使用了泛型,但是這並不是一個泛型方法。
//這只是類中一個普通的成員方法,只不過他的返回值是在宣告泛型類已經宣告過的泛型。
//所以在這個方法中才可以繼續使用 T 這個泛型。
public T getKey(){
return key;
}
/**
* 這個方法顯然是有問題的,在編譯器會給我們提示這樣的錯誤資訊"cannot reslove symbol E"
* 因為在類的宣告中並未宣告泛型E,所以在使用E做形參和返回值型別時,編譯器會無法識別。
public E setKey(E key){
this.key = keu
}
*/
}
/**
* 這才是一個真正的泛型方法。
* 首先在public與返回值之間的<T>必不可少,這表明這是一個泛型方法,並且聲明瞭一個泛型T
* 這個T可以出現在這個泛型方法的任意位置.
* 泛型的數量也可以為任意多個
* 如:public <T,K> K showKeyName(Generic<T> container){
* ...
* }
*/
public <T> T showKeyName(Generic<T> container){
System.out.println("container key :" + container.getKey());
//當然這個例子舉的不太合適,只是為了說明泛型方法的特性。
T test = container.getKey();
return test;
}
//這也不是一個泛型方法,這就是一個普通的方法,只是使用了Generic<Number>這個泛型類做形參而已。
public void showKeyValue1(Generic<Number> obj){
Log.d("泛型測試","key value is " + obj.getKey());
}
//這也不是一個泛型方法,這也是一個普通的方法,只不過使用了泛型萬用字元?
//同時這也印證了泛型萬用字元章節所描述的,?是一種型別實參,可以看做為Number等所有類的父類
public void showKeyValue2(Generic<?> obj){
Log.d("泛型測試","key value is " + obj.getKey());
}
/**
* 這個方法是有問題的,編譯器會為我們提示錯誤資訊:"UnKnown class 'E' "
* 雖然我們聲明瞭<T>,也表明了這是一個可以處理泛型的型別的泛型方法。
* 但是隻聲明瞭泛型型別T,並未宣告泛型型別E,因此編譯器並不知道該如何處理E這個型別。
public <T> T showKeyName(Generic<E> container){
...
}
*/
/**
* 這個方法也是有問題的,編譯器會為我們提示錯誤資訊:"UnKnown class 'T' "
* 對於編譯器來說T這個型別並未專案中宣告過,因此編譯也不知道該如何編譯這個類。
* 所以這也不是一個正確的泛型方法宣告。
public void showkey(T genericObj){
}
*/
public static void main(String[] args) {
}
}
2.5泛型方法的可變引數
public <T> void printMsg( T... args){
for(T t : args){
Log.d("泛型測試","t is " + t);
}
}
printMsg("111111",12.22,123,false);