1. 程式人生 > >Java基礎語法<十二> 泛型程序設計

Java基礎語法<十二> 泛型程序設計

清除 extend 原生態 cast color 強制 方式 限定 只為

1 意義

泛型程序設計意味著編寫的代碼可以被很多不同類型的對象所重用

常見應用 : ArrayList

2 K T V E ? object等的含義

類型變量使用大寫形式

E – Element (在集合中使用,因為集合中存放的是元素)

T – Type(Java 類)(需要時還可以用臨近的字母U和S)表示任意類型 S、U、V – 2nd、3rd、4th types

K – Key(鍵)

V – Value(值)

N – Number(數值類型)

? – 表示不確定的java類型(無限制通配符類型)

Object – 是所有類的根類,任何類的對象都可以設置給該Object引用變量,使用的時候可能需要類型強制轉換,但是用使用了泛型T、E等這些標識符後,在實際用之前類型就已經確定了,不需要再進行類型強制轉換。

3 泛型方法

public static <T> T getXXX(){

}

類型變量放在修飾符的後面,返回類型的前面

變量類型的限定

<T extends Comparable> T

一個類型變量或通配符可以有多個限定

T extends Comparable & Serializable

限定類型用&分隔,逗號用來分隔類型變量

在Java的繼承中,可以根據需要擁有的多個接口超類型,但限定中至多有一個類,如果用一個類作為限定,它必須是限定列表中的第一個。

4 泛型代碼和虛擬機

Java中的泛型基本上都是在編譯器這個層次來實現的。

生成的Java字節代碼中是不包含泛型中的類型信息的。

使用泛型的時候加上的類型參數,會被編譯器在編譯的時候去掉。 其實編譯器通過Code sharing方式為每個泛型類型創建唯一的字節碼表示,並且將該泛型類型的實例都映射到這個唯一的字節碼表示上。將多種泛型類形實例映射到唯一的字節碼表示是通過類型擦除(type erasue)實現的。

無論何時定義一個泛型類型,都自動提供一個相應的原始類型(raw type)。原始類型的名字就是刪除類型參數後的泛型類型名。擦除(erased)類型

變量,並替換為限定類型(無限定的變量用Object)

4.1 類型擦除

類型擦除指的是通過類型參數合並,將泛型類型實例關聯到同一份字節碼上。編譯器只為泛型類型生成一份字節碼,並將其實例關聯到這份字節碼上。類型擦除的關鍵在於從泛型類型中清除類型參數的相關信息,並且再必要的時候添加類型檢查和類型轉換的方法。 類型擦除可以簡單的理解為將泛型java代碼轉換為普通java代碼,只不過編譯器更直接點,將泛型java代碼直接轉換成普通java字節碼。

類型擦除的主要過程如下:

1.將所有的泛型參數用其最左邊界(最頂級的父類型)類型替換。

2.移除所有的類型參數。

PS:

1.虛擬機中沒有泛型,只有普通類和普通方法,所有泛型類的類型參數在編譯時都會被擦除,泛型類並沒有自己獨有的Class類對象。比如並不存在List<String>.class或是List<Integer>.class,而只有List.class。

2.創建泛型對象時請指明類型,讓編譯器盡早的做參數檢查(Effective Java,第23條:請不要在新代碼中使用原生態類型

3.不要忽略編譯器的警告信息,那意味著潛在的ClassCastException等著你。

4.靜態變量是被泛型類的所有實例所共享的。對於聲明為MyClass<T>的類,訪問其中的靜態變量的方法仍然是 MyClass.myStaticVar。不管是通過new MyClass<String>還是new MyClass<Integer>創建的對象,都是共享一個靜態變量。

5.泛型的類型參數不能用在Java異常處理的catch語句中。因為異常處理是由JVM在運行時刻來進行的。由於類型信息被擦除,JVM是無法區分兩個異常類型MyException<String>和MyException<Integer>的。對於JVM來說,它們都是 MyException類型的。也就無法執行與異常對應的catch語句。

5 泛型轉換

Java虛擬機中沒有泛型,只有普通的類和方法

所有的類型參數都用它們的限定類型替換

橋方法被合成來保持多態

為保持類型安全性,必要時插入強制類型轉換

6 約束與局限性

  • 不能用基本類型實例化類型參數
  • 運行時類型查詢只適用於原始類型
  • 不能創建參數化類型的數組
  • Varargs警告
  • 不能實例化類型變量
  • 泛型類的靜態上下文中類型變量無效
  • 不能拋出或捕獲泛型類的實例
  • 註意擦除後的沖突

7 通配符類型

7.1 <? extends T>

表示類型的上界,表示參數化類型的可能是T 或是 T的子類

7.2 <? super T >

表示類型下界(Java Core中叫超類型限定),表示參數化類型是此類型的超類型(父類型),直至Object

帶有超類型限定的通配符可以向泛型對象寫入,帶有子類型限定的通配符可以從泛型對象讀取。

7.3 無限定通配符 <?>

ps:

如果要從集合中讀取類型T的數據,並且不能寫入,可以使用 ? extends 通配符;(Producer Extends)

如果要從集合中寫入類型T的數據,並且不需要讀取,可以使用 ? super 通配符;(Consumer Super)

如果既要存又要取,那麽就不要使用任何通配符。

Java基礎語法<十二> 泛型程序設計