亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

java基礎-泛型

Original 2016-11-18 10:58:28 449
abstract:泛型的使用能使類型名稱作為類或者接口定義中的參數(shù),就像一般的參數(shù)一樣,使得定義的類型通用性更強?!》盒偷膬?yōu)勢: 編譯具有嚴格的類型檢查  java編譯器對于泛型代碼的類型檢查更加嚴格,能夠發(fā)現(xiàn)普通代碼中的一些運行時錯誤。消除類型轉(zhuǎn)化  //如下代碼未使用泛型,需要進行類型的轉(zhuǎn)化 List list = new ArrayList(); list.a

泛型的使用能使類型名稱作為類或者接口定義中的參數(shù),就像一般的參數(shù)一樣,使得定義的類型通用性更強。

 泛型的優(yōu)勢:

 編譯具有嚴格的類型檢查

  java編譯器對于泛型代碼的類型檢查更加嚴格,能夠發(fā)現(xiàn)普通代碼中的一些運行時錯誤。

消除類型轉(zhuǎn)化  

//如下代碼未使用泛型,需要進行類型的轉(zhuǎn)化
List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0);

//泛型的使用可以不適用類型轉(zhuǎn)化
List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0);   // no cast

能夠使程序員實現(xiàn)通用的算法

  通過使用泛型,使得一類不同的類型能夠進行通用的運算。

1 泛型

   泛型是將類型參數(shù)化的類或者接口。

1.1 泛型的聲明

  一般泛型的聲明類似如下:

class name<T1, T2, ..., Tn> { /* ... */ }

 

  尖括號中的參數(shù)就是類型參數(shù),參數(shù)由逗號隔開,類型參數(shù)可以是任何非基本數(shù)據(jù)類型的任何類型,泛型的接口聲明與上述泛型類類似。

1.2 泛型參數(shù)命名

  一般情況下,泛型類型參數(shù)的名稱是單個大寫字母,和變量名稱鮮明地區(qū)分開來。

  最通用的參數(shù)類型參數(shù)名稱為:

E - 元素 (被java集合框架應用)

K - 鍵

N - 數(shù)字

T - 類型

V - 值

S,U,V 等等 - 第二,第三, 第四類型

  在javaSE API中這些名稱被廣泛使用

1.3 調(diào)用和實例化泛型

  如需引用一個泛型,首先要進行一個泛型的調(diào)用,如下所示:

//傳入類型參數(shù),如下為String作為類型參數(shù)ArrayList<String> list;

  上述代碼可以看做個調(diào)用方法類似,不過是以類型為參數(shù),這一過程叫參數(shù)化類型,實例化泛型的語法如下:

//一下聲明和實例化一步完成ArrayList<String> list=new ArrayList<String>();

 

1.4 鉆石

  java7以后,只要編譯器能夠根據(jù)代碼的上下文判斷類型參數(shù),就可以將泛型的構造器的類型實參留空(<>)由于空的尖括號形狀就像鉆石,所以非正式的成為鉆石,如上述代碼可以簡寫為:

//注意構造器內(nèi)的參數(shù)已經(jīng)省略ArrayList<String> list=new ArrayList<>();

1.5 參數(shù)化類型作為類型參數(shù)

  泛型的類型參數(shù)也可以是參數(shù)話的泛型,如:

//省略構造器類型參數(shù)ArrayList<List<String>> list=new ArrayList<>();

 

2 原始類型

2.1定義

  原始類型是指沒有類型參數(shù)的泛型。例如一下聲明一個原始類型:

//ArrayList是一個泛型,因此List變量是原始類型ArrayList list=new ArrayList();

 

  原始類型的舊的java版本的遺產(chǎn),因為許多API類如集合類在JDK5之前不是泛型,為了向下兼容,將一個參數(shù)化的泛型對象賦值給一個原始類型是允許的:

Box<String> stringBox = new Box<>();
Box rawBox = stringBox;               // OK

 

 不過反過來,將一個原始類型賦值給一個參數(shù)化的泛型,編譯器將會給出警告:

Box rawBox = new Box();           
// rawBox是 Box<T>的原始類型Box<Integer> intBox = rawBox;    
 // 警告: unchecked conversion

 

  如果使用原始類型去調(diào)用隊形的泛型的泛型方法,同樣也會得到警告:

Box<String> stringBox = new Box<>();
Box rawBox = stringBox;
rawBox.set(8);  // warning: unchecked invocation to set(T)

 

  編譯器警告表明原始類型繞過了類型的檢查,而將可能出錯的風險留到了運行時,所以盡量不要使用原始類型。

2.2 未檢查錯誤信息

  如之前所提到的,當泛型和傳統(tǒng)語法混用時,你將會遇到一些如下的警告消息:

    Note: Example.java uses unchecked or unsafe operations.   

    Note: Recompile with -Xlint:unchecked for details.

  “unchecked”(未檢查的)這一術語表明編譯器沒有足夠的關于類型信息來執(zhí)行檢查以確保類型的安全,編譯器默認警用未檢查警告,但是會給出提示,如果想要啟用未檢查警告,在編譯時加入?yún)?shù) -Xlint:unchecked。

  如果想要完全禁用未檢查警告,可以編譯時加入?yún)?shù)-Xlint:-unchecked(注意與上述參數(shù)區(qū)別)或者使用注釋@SuppressWarnings("unchecked")。

3 泛型方法

  泛型方法是指引入自身的參數(shù)類型的方法,就像泛型的類型參數(shù)一樣,不過方法的類型參數(shù)的使用范圍僅限于方法自身??梢远x靜態(tài)和非靜態(tài)的泛型方法,同時也可以定義使用泛型構造器。

  泛型方法的語法含有位于方括號內(nèi)的類型參數(shù),位于方法返回類型之前,當然,非泛型的類也可以包含泛型方法。

   如下舉例說明泛型方法的聲明:

public class Util {
//以下方法為泛型方法
    public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
        return p1.getKey().equals(p2.getKey()) &&
               p1.getValue().equals(p2.getValue());
    }
}

public class Pair<K, V> {

    private K key;
    private V value;

    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public void setKey(K key) { this.key = key; }
    public void setValue(V value) { this.value = value; }
    public K getKey()   { return key; }
    public V getValue() { return value; }
}

完整的調(diào)用泛型方法的語法為:

//以下語句利用了上述定義的類Pair<Integer, String> p1 = new Pair<>(1, "apple");
Pair<Integer, String> p2 = new Pair<>(2, "pear");boolean same = Util.<Integer, String>compare(p1, p2);

 當然,如果編譯其能夠推測出類型,可省略泛型方法的類型參數(shù):

Pair<Integer, String> p1 = new Pair<>(1, "apple");
Pair<Integer, String> p2 = new Pair<>(2, "pear");boolean same = Util.compare(p1, p2);

4 限制類型參數(shù)范圍

  有時候你可能需要限定泛型的類型參數(shù),比如限定某個泛型的類型參數(shù)只能為Number或者是其子類或者繼承類。

  聲明類型參數(shù)的限定,就是在參數(shù)名稱之后跟上extends關鍵詞,然后跟上其上限,如Number,在這里extends通常意義上是指類的extends和接口的implements。,如一下方法的聲明:

public <U extends Number> void inspect(U u){
        System.out.println("T: " + t.getClass().getName());
        System.out.println("U: " + u.getClass().getName());
    }

 一個類型參數(shù)可以有多重限定,即extends關鍵詞后跟多個上限,用符號&隔開:

class D <T extends A & B & C> { /* ... */ }

 

5 泛型,繼承和子類型

  java中可以將一個類型的對象賦值給另外一個類型的變量,如果兩個類型相兼容的話,如可以將Integer類型的對象賦值給類型為Object的變量。在面向?qū)ο蟮男g語中,這是一種叫做“是一個”的關系,如Integer類型是一個Object類型,因此允許上述的賦值。方法包括泛型的方法的參數(shù)的傳遞也是如此,如

//如下進行類型參數(shù)化的ArrayList類型的元素類型為Number
ArrayList<Number> list=new ArrayLIst<Number>();
//其add方法參數(shù)類型也是Number,也可以使用其子類Integer的實例
list.add(new Integer(10));

  但是對于泛型的子類型關系,與普通的類型是有區(qū)別的,如下圖所示:

927750-20161117210838560-382514216.gif

箭頭表示子類型的關系,如Integer是Number的子類型,而Box<Integer>則不是Box<Number>的子類型,Box<Integer>和Box<Number>的共同的父類型是Object。

  你可以通過繼承或者實現(xiàn)一個泛型來成為該泛型一個子類型。類或者接口的類型參數(shù)之間的關系是由extends和implements語句決定的。

  比如集合類,ArrayList<E>實現(xiàn)List<E>,List<E>繼承Collection<E>所以ArrayList<String>是List<String>的子類型,List<String>是Collection<String>的子類型,只要不變更類型參數(shù),這種繼承關系就會保留:

927750-20161117210838560-382514216.gif

 現(xiàn)在自定義一個新的繼承List接口的接口:

//注意類型參數(shù)的名稱
interface PayloadList<E,P> extends List<E> {
  void setPayload(int index, P val);
  ...
}

 類型參數(shù)化的類型則由如下關系:

927750-20161117210838560-382514216.gif

Release Notes

Popular Entries