java泛型與泛型擦除
阿新 • • 發佈:2019-02-02
1:概念
泛型的本質是引數化型別,也就是說所操作的資料型別被指定為一個引數,在用到的時候再指定為具體的型別。
與其他語言不同,java的泛型被稱為偽泛型。它只在程式的原始碼中存在,在編譯後的位元組碼檔案中,泛型被轉化
成了原始型別(Raw Type)。因此對於執行期的Java語言來說,ArrayList<int>與ArrayList<String>一樣,
都是ArrayList類。Java語言中的這種泛型實現方法稱為型別擦除。
2:泛型類與泛型方法
定義 一個泛型類只需要在類的類名後面加上<>,再在裡面加上型別引數即可:
定義一個型別方法://泛型類Box public class Box<T> { private T t; public void add(T t) { this.t = t; } public T get() { return t; } }
//泛型方法printArray
public static < E > void printArray( E[] inputArray ){
// 輸出陣列元素
for ( E element : inputArray ){
System.out.printf( "%s ", element );
}
System.out.println();
}
3:型別擦除
由於java的型別被稱為偽型別,在編譯之後會將泛型轉化為原始型別
<span style="white-space:pre"> </span>ArrayList<String> arrayList1=new ArrayList<String>(); arrayList1.add("abc"); ArrayList<Integer> arrayList2=new ArrayList<Integer>(); arrayList2.add(123); System.out.println(arrayList1.getClass()==arrayList2.getClass()); //均為ArrayList型別,輸出true
當然,我們也可以通過反射為ArrayList新增不同的型別:
<span style="white-space:pre"> </span>ArrayList<Integer> arrayList=new ArrayList<Integer>();
arrayList.getClass().getMethod("add", Object.class).invoke(arrayList, "abc");
System.out.println(arrayList.get(0));//輸出abc
4:型別轉換
在呼叫泛型方法的時候,可以指定泛型,也可以不指定泛型。
在不指定泛型的情況下,泛型變數的型別為 該方法中的幾種型別的同一個父類的最小級,直到Object。
在指定泛型的時候,該方法中的幾種型別必須是該泛型例項型別或者其子類。
//一個簡單的泛型方法
public static <T> T add(T x,T y){
return y;
}
public static void main(String[] args) {
/**不指定泛型的時候*/
int i=Test2.add(1, 2); //兩個引數都是Integer,返回為Integer型別
Number f=Test2.add(1, 1.2);//一個Integer型別,一個double型別,返回為同一父類的最小級:Number型別
Object o=Test2.add(1, "asd");//一個Integer型別,一個String型別,返回為同一父類的最小級:Object 型別
/**指定泛型的時候*/
int a=Test2.<Integer>add(1, 2);//指定了Integer,所以只能為Integer型別或者其子類
int b=Test2.<Integer>add(1, 2.2);//編譯錯誤,指定了Integer,不能為Float
Number c=Test2.<Number>add(1, 2.2); //指定為Number,所以可以為Integer和Float
}
5:型別檢查
為了避免某些錯誤,java在編譯之前會對型別進行檢查。對於ArrayList list=new ArrayList();
new ArrayList()會在記憶體中開闢一個儲存空間,可以儲存任何的型別物件。而真正涉及型別檢查的是它的引用list。所以執行下面程式碼會有如下結果:
ArrayList list1 = new ArrayList<Integer>();//編譯通過,但是會有警告
list1.add("abc");//編譯通過,因為list1引用申明時沒有指定型別
System.out.println(list1.get(0));//輸出abc
ArrayList<Integer> list2 = new ArrayList();//編譯通過,但是會有警告
list2.add("abc");//編譯錯誤,list2只能新增int型別
ArrayList<Integer> list3 = new ArrayList<>();//編譯通過,沒有警告