1. 程式人生 > >java泛型與泛型擦除

java泛型與泛型擦除

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<>();//編譯通過,沒有警告