Java基础语法十二 泛型程序设计
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 <? extends T>?
表示類型的上界,表示參數化類型的可能是T 或是 T的子類
7.2 超類型限定 super <? super T >
表示類型下界(Java Core中叫超類型限定),表示參數化類型是此類型的超類型(父類型),直至Object
帶有超類型限定的通配符可以向泛型對象寫入,帶有子類型限定的通配符可以從泛型對象讀取。
7.3 無限定通配符?<?>
ps:
如果要從集合中讀取類型T的數據,并且不能寫入,可以使用 ? extends 通配符;(Producer Extends)
如果要從集合中寫入類型T的數據,并且不需要讀取,可以使用 ? super 通配符;(Consumer Super)
如果既要存又要取,那么就不要使用任何通配符。
8 tag問題
8.1?什么是泛型、為什么要使用以及泛型擦除
泛型,即“參數化類型”。
創建集合時就指定集合元素的類型,該集合只能保存其指定類型的元素,避免使用強制類型轉換。
Java編譯器生成的字節碼是不包涵泛型信息的,泛型類型信息將在編譯處理是被擦除,這個過程即類型擦除。泛型擦除可以簡單的理解為將泛型java代碼轉換為普通java代碼,只不過編譯器更直接點,將泛型java代碼直接轉換成普通java字節碼。
類型擦除的主要過程如下:
1).將所有的泛型參數用其最左邊界(最頂級的父類型)類型替換。
2).移除所有的類型參數。
?
轉載于:https://www.cnblogs.com/loveincode/p/7207594.html
總結
以上是生活随笔為你收集整理的Java基础语法十二 泛型程序设计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 要成为信托公司股东需具备什么条件
- 下一篇: arc 和 非arc兼容