iT邦幫忙

2026 iThome 鐵人賽

0
Build on Google AI

把Google AI當夥伴打造個人高效Coding工作流系列 第 11 篇

第十一天泛型機制、型別擦除與PECS原則

  • 分享至 

  • xImage
  •  

一、 為什麼需要泛型(Generics)?

  • 編譯期型別安全:在編譯階段就抓出型別不相容問題,將執行期的 ⁠ClassCastException⁠ 提前消滅在編譯期。
  • 消滅強制轉型:從集合取值時由編譯器自動轉換,省去寫 ⁠(User) list.get(0)⁠ 這類冗長又危險的代碼。

二、 核心底層:型別擦除(Type Erasure)
Java泛型是偽泛型,採用這套設計是為了與Java 5以前的老舊程式碼達成100%向後相容。

  • 運作機制:泛型資訊只存在於源碼與編譯期。編譯成.class⁠字節碼後,所有的型別參數都會被擦除為它的上限(未指定上限則擦除為⁠Object⁠)。
  • 型別擦除帶來的四大物理限制:
  1. 不能⁠new T()⁠:因為執行JVM根本不知道⁠T到底是什麼類別,無法在Heap分配空間。
  2. 不能建立泛型陣列(如 ⁠new T[10]⁠ 或 ⁠new List[10]⁠):陣列具備協變性在執行期知道具體型別,與泛型的型別擦除相衝突。
  3. 不支援基本型別:必須使用包裝型別List⁠,因為基本型別無法繼承自Object⁠。
  4. 靜態上下文中不能引用類別泛型參數:⁠static⁠成員由Class共享,與個別實例的泛型無關。

三、 萬用字元與變異性(Variance)

  • 不變性(Invariance):雖然Integer⁠是Number⁠的子類別,但⁠List⁠絕對不是List⁠的子類別!兩者不能互相賦值,否則會破壞型別安全。
  • 萬用字元⁠?⁠:代表未知的某個型別,加API的彈性。

四、 架構設計必背:PECS原則(Producer Extends, Consumer Super)

  • 這是設計通用函式庫與API時核心的設計法則:
  1. Producer Extends:
    語義:適合生產者,果這個參數的主要目的是提供資料讓你讀取。
    特性:可以安全讀出資料並當成T⁠使用;但嚴禁寫入任何元素(除了 ⁠null⁠),因為編譯器無法確定裡面到底是哪一種具體子類別。
  2. Consumer Super:
    語義:適合消費者如果這個參數的主要目的是接收資料讓你寫入(Write / Consume)。
    特性:可以安全寫入⁠T或⁠T⁠的子類別實體;但讀取出來的型別只能被當作 Object⁠,因為只知道它是T⁠的某個父類別,無法確定具體型態。
  3. 經典範例:⁠Collections.copy(List<? super T> dest, List<? extends T> src)⁠。
    ⁠src⁠是生產者(讀出來),所以用 ⁠extends⁠;
    ⁠dest⁠是消費者(寫進去),所以用 ⁠super⁠。

上一篇
第十天例外架構體系Checked vs Unchecked、資源洩漏防禦與自訂業務例外封裝
下一篇
第十二天ArrayList 擴容演算法、拷貝開銷與LinkedList快取局部性劣勢
系列文
把Google AI當夥伴打造個人高效Coding工作流 共 13 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言