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

java基礎(chǔ)-泛型

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

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

 泛型的優(yōu)勢:

 編譯具有嚴(yán)格的類型檢查

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

消除類型轉(zhuǎn)化  

//如下代碼未使用泛型,需要進(jì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

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

  通過使用泛型,使得一類不同的類型能夠進(jìn)行通用的運(yùn)算。

1 泛型

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

1.1 泛型的聲明

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

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

 

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

1.2 泛型參數(shù)命名

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

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

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

K - 鍵

N - 數(shù)字

T - 類型

V - 值

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

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

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

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

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

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

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

 

1.4 鉆石

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

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

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

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

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

 

2 原始類型

2.1定義

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

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

 

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

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

 

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

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

 

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

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

 

  編譯器警告表明原始類型繞過了類型的檢查,而將可能出錯(cuò)的風(fēng)險(xiǎn)留到了運(yùn)行時(shí),所以盡量不要使用原始類型。

2.2 未檢查錯(cuò)誤信息

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

    Note: Example.java uses unchecked or unsafe operations.   

    Note: Recompile with -Xlint:unchecked for details.

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

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

3 泛型方法

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

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

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

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);

 當(dāng)然,如果編譯其能夠推測出類型,可省略泛型方法的類型參數(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ù),比如限定某個(gè)泛型的類型參數(shù)只能為Number或者是其子類或者繼承類。

  聲明類型參數(shù)的限定,就是在參數(shù)名稱之后跟上extends關(guān)鍵詞,然后跟上其上限,如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());
    }

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

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

 

5 泛型,繼承和子類型

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

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

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

927750-20161117210838560-382514216.gif

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

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

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

927750-20161117210838560-382514216.gif

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

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

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

927750-20161117210838560-382514216.gif

Versionshinweise

Beliebte Eintr?ge