java泛型
一、泛型帶來的好處
1. 類型安全。類型錯誤在編譯期間就被捕獲到(不會在運行時當作 java.lang.ClassCastException),提高程序的可靠性。
2.消除了代碼中許多的強制類型轉換,增強了代碼的可讀性。
3. 泛型是什麼不會對對象帶來影響。
問題:
定義一個泛型類最後到底會生成幾個類,比如 ArrayList 到底有幾個類 ?
定義一個泛型方法最終會有幾個方法在 class 文件中?
為什麼泛型參數不能是基本類型呢?
ArrayList 是一個類嗎?
ArrayList 和 List 是什麼關係?這幾個類型的引用能相互賦值嗎?
二、泛型概念
**泛型的本質是參數化類型**
1.泛型基本上都是在編譯器這個層次來實現。生成的 java字節碼 中不包含泛型中的類型信息
( 使用泛型時加上類型參數,編譯器編譯時去掉,這個過程稱為類型擦除 )
extends A>擦除後變為A
擦除後變為Object
2.泛型沒有獨立的 Class類對象,單獨記錄在Class文件的attributes域內
3.靜態變量被泛型類的所有實例共享。
4.泛型的類型參數不能用在 java異常處理的 catch語句中。
(異常處理是由 JVM運行時進行的,泛型在編譯後對JVM不可見。)
類型擦除的基本過程:
找到用來替換類型參數的具體類(一般 Object),如果指定了類型參數的上界的話,則使用這個上 界。把代碼中的類型參數都替換成具體類,同時去掉出現的類型聲明,即去掉 <> 的內容。
泛型的實現原理:
不能實現真正的泛型,只能使用類型擦除來實現偽泛型,雖然不會有類型膨脹,但會出現許多新的問題。
保證類型安全:
既然類型擦除了,如何保證我們只能使用泛型變量限定的類型?
答:java編譯器是通過先檢查代碼中泛型的類型,然後再進行類型擦除,在進行編譯。
自動類型轉換:
因為類型擦除的問題,所有的泛型類型變量最後都會被替換為原始類型(Object)。既然都替換為原始類,那麼為什麼我們在獲取時,不需要進行強制類型轉換?
答:編譯器生成 class文件中會在你調用泛型方法完成之後返回調用點之前加上類型轉換的操作,比如上下文的 get 函數,就在 get方法完成後,jump回原本的賦值操作的指令位置之前加入了強制轉換,轉換的類型由編譯器推導。
泛型參數的繼承關係:
根據Liskov(里氏替換原則 )替換原則,子類是可以替換父類的。但是反過來,需要進行強制類型轉換,但是編譯器並不能保證運行時這種轉換是合法的。
引入泛型後類型系統增加了兩個維度:一個是類型參數自身的繼承體系結構,一個是泛型類或接口自身的繼承體系結構。
閱讀更多 給我一杯溫開水 的文章