1. 程式人生 > >第8篇 Java泛型

第8篇 Java泛型

泛型:jdk1.5版本以後出現的一個安全機制。表現格式:< >

好處:

1:將執行時期的問題ClassCastException問題轉換成了編譯失敗,體現在編譯時期,程式設計師就可以解決問題。

2:避免了強制轉換的麻煩。

 

只要帶有<>的類或者介面,都屬於帶有型別引數的類或者介面,在使用這些類或者介面時,必須給<>中傳遞一個具體的引用資料型別。

 

泛型技術:其實應用在編譯時期,是給編譯器使用的技術,到了執行時期,泛型就不存在了。

為什麼? 因為泛型的擦除:也就是說,編輯器檢查了泛型的型別正確後,在生成的類檔案中是沒有泛型的。

在執行時,如何知道獲取的元素型別而不用強轉呢?

泛型的補償:因為儲存的時候,型別已經確定了是同一個型別的元素,所以在執行時,只要獲取到該元素的型別,在內部進行一次轉換即可,所以使用者不用再做轉換動作了。

 

什麼時候用泛型類呢?

當類中的操作的引用資料型別不確定的時候,以前用的Object來進行擴充套件的,現在可以用泛型來表示。這樣可以避免強轉的麻煩,而且將執行問題轉移到的編譯時期。

----------------------------------------------------------

泛型在程式定義上的體現:

//泛型類:將泛型定義在類上。

class Tool<Q> {

private Q obj;

public  void setObject(Q obj) {

this.obj = obj;

}

public Q getObject() {

return obj;

}

}

//當方法操作的引用資料型別不確定的時候,可以將泛型定義在方法上。

public <W> void method(W w) {

System.out.println("method:"+w);

}

//靜態方法上的泛型:靜態方法無法訪問類上定義的泛型。如果靜態方法操作的引用資料型別不確定的時候,必須要將泛型定義在方法上。

public static <Q> void function(Q t) {

System.out.println("function:"+t);

}

//泛型介面.

interface Inter<T> {

void show(T t);

}

class InterImpl<R> implements Inter<R> {

public void show(R r) {

System.out.println("show:"+r);

}

}

------------------------------------------------------------

泛型中的萬用字元:可以解決當具體型別不確定的時候,這個萬用字元就是 ?  ;當操作型別時,不需要使用型別的具體功能時,只使用Object類中的功能。那麼可以用 ? 萬用字元來表未知型別。

 

泛型限定:

上限:?extends E:可以接收E型別或者E的子型別物件。

下限:?super E:可以接收E型別或者E的父型別物件。

 

上限什麼時候用:往集合中新增元素時,既可以新增E型別物件,又可以新增E的子型別物件。為什麼?因為取的時候,E型別既可以接收E類物件,又可以接收E的子型別物件。

 

下限什麼時候用:當從集合中獲取元素進行操作的時候,可以用當前元素的型別接收,也可以用當前元素的父型別接收。

 

泛型的細節:

1)、泛型到底代表什麼型別取決於呼叫者傳入的型別,如果沒傳,預設是Object型別;

2)、使用帶泛型的類建立物件時,等式兩邊指定的泛型必須一致;

原因:編譯器檢查物件呼叫方法時只看變數,然而程式執行期間呼叫方法時就要考慮物件具體型別了;

3)、等式兩邊可以在任意一邊使用泛型,在另一邊不使用(考慮向後相容);

ArrayList<String> al = new ArrayList<Object>();  //錯

//要保證左右兩邊的泛型具體型別一致就可以了,這樣不容易出錯。

ArrayList<? extends Object> al = new ArrayList<String>();

al.add("aa");  //錯

//因為集合具體物件中既可儲存String,也可以儲存Object的其他子類,所以新增具體的型別物件不合適,型別檢查會出現安全問題。 ?extends Object 代表Object的子型別不確定,怎麼能新增具體型別的物件呢?

public static void method(ArrayList<? extends Object> al) {

al.add("abc");  //錯

//只能對al集合中的元素呼叫Object類中的方法,具體子型別的方法都不能用,因為子型別不確定。

}