泛型允許在定義類、接口、方法時使用類型參數,實際使用時再指定具體類型。核心優勢:編譯期類型安全、消除強制轉型、代碼復用。
// 多類型參數
public interface List<E> extends Collection<E> {}
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {}
// 使用:菱形語法 (JDK 7+)
List<String> list = new ArrayList<>();
Map<Integer, String> map = new HashMap<>();
// 1. 固化類型參數
public class StringList extends ArrayList<String> {}
// 2. 保持類型參數
public class MyList<T> extends ArrayList<T> {}
// 3. 擦除為原始類型 (不推薦)
public class RawList extends ArrayList {}
Java 泛型僅存在於編譯期,運行期 JVM 看到的是原始類型(擦除後的類型)。
List<String> a1 = new ArrayList<>(); List<Integer> a2 = new ArrayList<>(); System.out.println(a1.getClass() == a2.getClass()); // true System.out.println(a1.getClass()); // class java.util.ArrayList
限制:靜態上下文中不能使用類型參數(因為類只有一份字節碼)。
class Test<T> {
// 錯誤: static T field; static { T t; } static void foo() { T t; }
}
?List<?> 表示元素類型未知的列表。只能 get() 返回 Object,不能 add()(除 null)。
? extends TList<? extends Number>:元素是 Number 或其子類。只能讀,不能寫(生產者 extends)。
void printSum(List<? extends Number> list) {
double sum = 0;
for (Number n : list) sum += n.doubleValue(); // OK
// list.add(10); // 編譯錯誤
}
? super TList<? super Integer>:元素是 Integer 或其父類。只能寫,讀出為 Object(消費者 super)。
void addIntegers(List<? super Integer> list) {
list.add(10); // OK
list.add(new Integer(20)); // OK
Object obj = list.get(0); // 只能作為 Object 讀取
}
Producer Extends, Consumer Super。
作為生產者(只讀)用 extends,作為消費者(只寫)用 super。
經典例子:Collections.copy(List<? super T> dest, List<? extends T> src)。
方法級別定義類型參數,放在修飾符與返回類型之間。
public static <T> void swap(T[] arr, int i, int j) {
T tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp;
}
// 調用:swap(new String[]{"a","b"}, 0, 1); // T 推斷為 String
泛型方法可表達多參數類型關係,如 <T> T max(T a, T b)。
List),等同擦除後類型(List<Object> 的擦除)。List<String> gs = new ArrayList<>(); List raw = gs; // 擦除,raw 元素類型視為 Objectclass MyList<T> implements List<T> { public void add(T t) {} } → 字節碼中同時有 add(T) 和 add(Object)(橋接)。| 陷阱 | 原因 | 對策 |
|---|---|---|
| 無法創建泛型數組 | 擦除導致運行期類型不匹配 | 用 List<T> 或 T[] arr = (T[]) new Object[size] (需 @SuppressWarnings) |
| instanceof 檢查泛型 | 運行期類型信息已擦除 | 用 list instanceof List<?> 或檢查元素類型 |
| 異常捕獲泛型 | Catch 塊不能用類型參數 | 捕獲具體異常類或基類 |
| 重載泛型方法擦除衝突 | 擦除後簽名相同 | 避免此類重載,改用不同方法名 |
extends/super) 增加靈活性。@SuppressWarnings("unchecked") 精確抑制不可避免的警告(如數組轉型)。<T extends Comparable<T>>)。