首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 泛型深度解析:從類型擦除到通配符上下界的完整指南

     編輯:Java 綜合教學

為什麼需要泛型?

Java 集合在無泛型時代默認存 Object,導致兩大痛點:

  1. 取出元素需強制轉型,易拋 ClassCastException(編譯期不報錯,運行期崩潰)。
  2. 集合不記住元素類型,編碼時依賴開發者記憶,維護成本高。
// 無泛型隱患
List list = new ArrayList();
list.add("hello");
list.add(100); // 允許混入 Integer
String s = (String) list.get(1); // 運行時拋 ClassCastException

泛型本質:參數化類型

List<String> 將類型參數化,String 為類型實參,接口定義中的 E 為類型形參。編譯器據此:

  • 拒絕 list.add(100)(編譯報錯)。
  • get() 直接返回 String,無需轉型。

源碼視角:ArrayList 泛型實現

public class ArrayList<E> ... {
    transient Object[] elementData; // 底層仍是 Object 數組
    public boolean add(E e) {
        elementData[size++] = e; // 存入時無類型檢查(擦除後)
        return true;
    }
    public E get(int index) {
        return (E) elementData[index]; // 取出時編譯器插入轉型指令
    }
}

泛型信息僅存在編譯期,字節碼中被擦除為原始類型(Object),這就是「類型擦除」。

自定義泛型類、接口、方法

// 泛型類
class Box<T> {
    private T data;
    public Box(T data) { this.data = data; }
    public T getData() { return data; }
}

// 泛型方法(類不泛型,方法泛型)
public static <T> void print(T t) { System.out.println(t); }

關鍵結論:Box<String> 和 Box<Integer> 在運行期是同一個 Class 對象(Box.class),邏輯上視為不同類型,物理上共享字節碼。

類型通配符與上下界

泛型不具備多態性:Box<Number> 不是 Box<Integer> 的父類。為解決「同時接受 Number 及其子類」需求,引入通配符 ?:

// 無界通配符:邏輯父類
void print(Box<?> box) { ... }

// 上界:只接受 Number 及子類
void printNumber(Box<? extends Number> box) { ... }

// 下界:只接受 Number 及父類
void addNumber(Box<? super Number> box) { ... }
  • extends:讀取安全(取出必是 Number),寫入受限(只能寫 null)。
  • super:寫入安全(可寫 Number 及子類),讀取只能作 Object。

PECS 原則速記

Producer Extends, Consumer Super

  • 頻繁 讀取(生產者)→ 用 ? extends T。
  • 頻繁 寫入(消費者)→ 用 ? super T。

進階陷阱與最佳實踐

  1. 無泛型數組:new List<String>[10] 編譯錯誤,改用 List<List<String>>。
  2. 靜態成員不可用類型參數:static T field 非法。
  3. 異常類不能泛型:class MyEx<T> extends Exception 非法。
  4. 實例化類型參數非法:new T() 需借助反射或工廠模式。

總結

泛型將類型檢查前置到編譯期,消除運行期轉型風險,配合通配符上下界實現靈活的 API 設計。理解「擦除機制」與「PECS 原則」是駕馭 Java 泛型的核心鑰匙。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved