泛型

(一).  泛型java

1.1 介紹數組

  泛型是JDK5.0新增長的一個特性,泛型的本質是參數化類型,即所操做的數據類型都被指定爲一個參數。這種類型參數能夠用在類、接口、和方法的建立中,分別稱爲泛型類、泛型接口、泛型方法。Java語言引入泛型的好處是安全簡單。安全

1.2 認識泛型測試

  在JDK5.0以前,沒有泛型的狀況下,經過對類型Object的引用來實現參數的"任意化",但"任意化"帶來的缺點是須要顯示的強制類型轉換,此種轉換要求開發者對實際參數類型預知的狀況下進行的。對於強制類型轉換錯誤的狀況,編譯器可能不會提示錯誤,但在運行的時候會出現異常,這是一個安全隱患。this

1.3 泛型的優點spa

  使用泛型的優點在於編譯期間檢查類型,捕捉類型不匹配錯誤,而且全部的轉換都是自動和隱式多的,提升代碼複用率。code

(二).  泛型的使用 對象

2.1  泛型定義blog

  實例化泛型類的語法結構以下:繼承

  1 classname<type-param-list> obj = new classname<type-param-list> (cons-arg-list);  

  泛型定義一般使用一個惟一的大寫字母表示一個類型參數。

2.2  代碼演示

 1 //建立泛型類
 2 public class Generic <T> {
 3     private T ob;//定義泛型成員變量
 4     public Generic(T ob){
 5         this.ob = ob;
 6     }
 7     public T getOb(){
 8         return ob;
 9     }
10     public void setOb(T ob){
11         this.ob = ob;
12     }
13     public void showType(){
14         System.out.println("實際類型是:" + ob.getClass().getName());
15     }
16 }

  接下來建立類:

 1 //建立測試類,用於解釋泛型的使用方法
 2 public class GenericDemo {
 3     public static void main(String[] args) {
 4         //定義泛型類Genneric的一個Integer版本
 5         Generic<Integer> intOb = new Generic<Integer>(88);
 6         intOb.showType();
 7         int i = intOb.getOb();
 8         System.out.println("value=" + i);
 9         System.out.println("---------------------------------");
10         //定義泛型類Genneric的一個String版本
11         Generic<String> strOb = new Generic<String>("Hello");
12         strOb.showType();
13         String s = strOb.getOb();
14         System.out.println("value=" + s);
15     }
16 }

  運行結果:

1 實際類型是:java.lang.Integer
2 value=88
3 ---------------------------------
4 實際類型是:java.lang.String
5 value=Hello

2.3  理解泛型需注意3點

  • 泛型的類型參數是類類型(包括自定義類),不能是基本數據類。
  • 同一種泛型能夠對應多個版本(由於類型參數是不肯定的),不一樣版本的泛型類實例是不兼容的。
  • 泛型的類型參數能夠有多個。

(三).  有界類型

3.1  介紹

  在有些時候須要對類型參數的取值進行必定程度的限制,以使數據具備可操做性。爲了處理這種狀況,Java提供了有界類型。在指定類型參數時可使用extends關鍵字限制此類型參數表明的類必須繼承自指定父類或父類自己。好比建立一個類:public class BoundGeneric<T extends Number>{},BoundGeneric類的定義中,使用extends關鍵字將T的類型限制爲Number類及其子類。

3.2  注意

  在使用extends(如:T extends someClass)聲明的泛型類進行實例化時,運行傳遞的類型參數是:若是someClass是類,能夠傳遞someClass自己及其子類,若是someClass是接口,則能夠傳遞實現接口的類。

3.3  通配符

  通配符由」?「來表示,表明一個未知類型。

  例如:public static void func(Generic <?> T){}或者結合有界類型使用

     public static void func(Generic <? extends Number> T)

(四).  泛型的侷限

4.1 泛型的侷限性

  其實Java並無真正的實現泛型,是編譯器在編譯的時候在字節碼上了作手腳(成爲擦除),這種實現理念形成java泛型自己有不少漏洞,侷限性很大。其中大多數限制性是由類型擦除引發的。

  • 泛型不能被實例化。但能夠經過調用Class.newInstance和Array.newInstance方法,利用反射構造泛型對象和數組。
  • 不能實例化泛型數組,即不能建立一個類型特定的泛型引用數組。如:Gen<String> []arrays = new Gen<String> [100];該語句是非法語句,由於會損害類型安全,可是若是使用通配符,就能夠建立泛型類型的引用數組,如:Gen<?> []arrays = new Gen<?> [10];
  • 不能用類型參數替換基本類型。由於擦除類型後原先的類型參數被Object或者限定類型替換,而基本類型是不能被對象所存儲的,可是可使用基本類型的包裝類來解決此問題。
  • 異常。不能拋出也不能捕獲泛型類的異常對象,使用泛型類來擴展Throwable也是非法的。
1 public class GenericException <T> extends Exception{
2     //泛型類沒法繼承Throwable,非法  
3 }

  不能在catch子句中使用類型參數,以下面的方法將不能編譯:

1 public static <T extends Throwable> void doWork(Class<T>  t){
2     try {
3     } catch (T e) {//不能捕獲類型參數異常
4     }
5 }

  可是,在異常聲明中可使用類型參數。下面這個是合法的:

1 public static <T extends Throwable> void doWork(T t) throws T {
2     try {
3     } catch (Throwable realCause) {//不能捕獲類型參數異常
4         throw t;        
5     }
6 }
  • 靜態成員。不能在靜態變量或者靜態方法中引用類型參數。以下述語句是非法的:
1 public class Gen<T>{
2     //靜態變量不能引用類型參數
3     static T ob;
4     //靜態方法不能引用類型參數
5     static T getOb(){
6         return ob;
7     }
8 }

  儘管不能在靜態變量或靜態方法中引用類型參數,但能夠聲明靜態泛型方法。

(五).  技巧

  當方法靜態時,不能訪問類上定義的泛型,若是靜態方法使用泛型,只能將泛型定義在方法上,注意放置位置:public static <Y> void method(Y obj)

  ? extends E :接收E類型或者E的子類對象((對於自己來講是)上限)

  ? super E  :接收E類型或者E的父類型(下限)

  在集合存元素時,通常使用上限,由於這樣取出都是按照上限類型來運算,不會出現安全隱患。

  何時使用下限呢?

  一般對集合中的元素進行取出操做時,能夠用下限。

相關文章
相關標籤/搜索