天天看點

java(36):泛型

日期:2017/11/25

     泛型的使用能夠解決處理不同類型資料時遇到的困難。泛型是Java SE 1.5的新特性,泛型的本質是參數化類型,也就是說所操作的資料類型被指定為一個參數。這種參數類型可以用在類、接口和方法的建立中,分别稱為泛型類、泛型接口、泛型方法。 Java語言引入泛型的好處是安全簡單。

     在Java SE 1.5之前,沒有泛型的情況的下,通過對類型Object的引用來實作參數的“任意化”,“任意化”帶來的缺點是要做顯式的強制類型轉換,而這種轉換是要求開發者對實際參數類型可以預知的情況下進行的。對于強制類型轉換錯誤的情況,編譯器可能不提示錯誤,在運作的時候才出現異常,這是一個安全隐患。

     泛型的好處是在 編譯的時候檢查類型安全,并且所有的強制轉換都是自動和隐式的,以提高代碼的重用率。

代碼例子1:

package com.code.generic_paradigm;
//ArrayList<String> a  ; ArrayList  b
import java.util.ArrayList;

public class test02 {
  public static void main(String[] args){
    ArrayList<String> a = new ArrayList<String>();  
    ArrayList  b = new ArrayList();  
    Class c1 = a.getClass();  
    Class c2 = b.getClass();  
    System.out.println(c1.getClass().getName());
    System.out.println(c2.getClass().getName());
    System.out.println(c1 == c2); //true  
  }
}      

代碼例子2:

package com.code.generic_paradigm;

class FX<T>{
  private T ob;
  public FX(T ob){
    this.ob = ob ;    
  }
  public T getob(){
    return ob;
  }
  public void showetype(){
    System.out.println("T real parttern is :"+ob.getClass().getName());
  }
}

public class test01 {
  public static void main(String [] args){
    FX<Integer> intob = new FX<Integer>(100) ;
    intob.showetype();
    System.out.println("value="+intob.getob());
    System.out.println("------------------");
    
    FX<String> strob = new FX<String>("mmb");
    strob.showetype();
    System.out.println("value="+strob.getob());
  }

}      

輸出結果:

T real parttern is :java.lang.Integer
value=100
------------------
T real parttern is :java.lang.String
value=mmb      

泛型的好處:

(1)類型安全。 

通過知道使用泛型定義的變量的類型限制,編譯器可以更有效地提高Java程式的類型安全。 

(2)消除強制類型轉換。 

消除源代碼中的許多強制類型轉換。這使得代碼更加可讀,并且減少了出錯機會。所有的強制轉換都是自動和隐式的。

(3)提高性能。 

[java] 

​​view plain​​​

 ​​​copy​​

 ​​​​​​​​

  1. new ArrayList();
  2. "CSDN_SEU_Cavin ");
  3. 0);

[java] 

​​view plain​​​

 ​​​copy​​

 ​​​​​​​​

  1. new ArrayList<String>();
  2. "CSDN_SEU_Cavin ");
  3. 0);

對于上面的兩段程式,由于泛型所有工作都在編譯器中完成,javac編譯出來的位元組碼是一樣的(隻是更能確定類型安全),那麼何談性能提升呢?是因為在泛型的實作中,編譯器将強制類型轉換插入生成的位元組碼中,但是更多類型資訊可用于編譯器這一事實,為未來版本的 JVM 的優化帶來了可能。

注意事項

(1)泛型的類型參數隻能是類類型(包括自定義類),不能是簡單類型。

(2)泛型的類型參數可以有多個。

(3)不能對确切的泛型類型使用instanceof操作。如下面的操作是非法的,編譯時會出錯。

[java] 

​​view plain​​​

 ​​​copy​​

 ​​​​​​​​

  1. if(ex_num instanceof FX<Number>){
  2. }

(4)不能建立一個确切的泛型類型的數組。

[java] 

​​view plain​​​

 ​​​copy​​

 ​​​​​​​​

  1. new List<String>[10]; // Not really allowed.
  2. Object o = lsa;
  3. Object[] oa = (Object[]) o;
  4. new ArrayList<Integer>();
  5. new Integer(3));
  6. 1] = li; // Unsound, but passes run time store check
  7. 1].get(0); // Run-time error: ClassCastException.

這種情況下,由于JVM泛型的擦除機制,在運作時JVM是不知道泛型資訊的,是以可以給oa[1]賦上一個ArrayList<Integer>而不會出現異常,但是在取出資料的時候卻要做一次類型轉換,是以就會出現ClassCastException,如果可以進行泛型數組的聲明,上面說的這種情況在編譯期将不會出現任何的警告和錯誤,隻有在運作時才會出錯。

下面采用通配符的方式是被允許的:

[java] 

​​view plain​​​

 ​​​copy​​

 ​​​​​​​​

  1. new List<?>[10]; // OK, array of unbounded wildcard type.
  2. Object o = lsa;
  3. Object[] oa = (Object[]) o;
  4. new ArrayList<Integer>();
  5. new Integer(3));
  6. 1] = li; // Correct.
  7. 1].get(0); // OK