JDK 5 引入泛型,提供編譯期型別安全、消除強制轉型、支援參數化類型。核心原理是型別擦除:執行期泛型資訊被擦除,僅保留原始類型(Raw Type)與必要的檢查轉型碼。
public class Box<T> {
private T value;
public T get() { return value; }
public void set(T value) { this.value = value; }
}
// 使用
Box<String> box = new Box<>();
box.set("hello");
String s = box.get(); // 無需轉型
public class Pair<K, V> {
private K key; private V value;
public Pair(K k, V v) { key = k; value = v; }
public K getKey() { return key; }
public V getValue() { return value; }
}
Pair<String, Integer> p = new Pair<>("age", 25);
? 與型別邊界| 語法 | 名稱 | 含義 | 典型用途 |
|---|---|---|---|
<?> | 無界通配符 | 任意型別,相當於 <? extends Object> | 只讀操作、List<?> printAll(List<?> list) |
<? extends T> | 上界通配符 | T 或 T 的子型別(協變) | 讀取集合元素、sum(List<? extends Number>) |
<? super T> | 下界通配符 | T 或 T 的父型別(逆變) | 寫入集合元素、addAll(List<? super Integer>) |
extends。super。// 生產者:只讀
public double sum(List<? extends Number> list) { ... }
// 消費者:只寫
public void addIntegers(List<? super Integer> list) {
list.add(1); // OK
list.add(2); // OK
// Number n = list.get(0); // 編譯錯誤,只能取 Object
}
public class Util {
// 單型別參數
public static <T> void swap(T[] arr, int i, int j) {
T tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp;
}
// 多型別參數
public static <K, V> Map<K, V> newMap() {
return new HashMap<>();
}
// 配合邊界
public static <T extends Comparable<T>> T max(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
}
List 和 List 都是 List(Raw Type)。new T()、T[] arr = new T[10]、instanceof T、靜態欄位共享。new List[10] 編譯錯誤。List<?>[] arr = new List<?>[10];List<List<String>> 替代。T... 實際是 T[],會產生「unchecked」警告,@SafeVarargs 抑制。// 遞迴型別界限:Enum、Comparable 常見模式
public class Enum<E extends Enum<E>> { ... }
public interface Comparable<T> { int compareTo(T o); }
// 自定義 Builder 模式
public class Builder<T extends Builder<T>> {
public T setName(String n) { ...; return (T) this; }
}
class PersonBuilder extends Builder<PersonBuilder> { ... }
List<E>。<T extends Comparable<? super T>>)。@SafeVarargs 消除可變參數警告(確認安全時)。<>、Java 10 var)簡化代碼。public class TypeSafeContainer {
private Map<Class<?>, Object> map = new HashMap<>();
public <T> void put(Class<T> type, T value) {
map.put(type, value);
}
public <T> T get(Class<T> type) {
return type.cast(map.get(type));
}
}
// 使用
TypeSafeContainer c = new TypeSafeContainer();
c.put(String.class, "hello");
c.put(Integer.class, 42);
String s = c.get(String.class); // 型別安全
Integer i = c.get(Integer.class);