<K, V> void put(K key, V value) { ... }
類似 C++ 模板,但 泛型實際類型必須為引用型別(不可用 int 等基本型別)。
<T> T add(T a, T b) {
// return a + b; // 編譯錯誤!T 不保證有 + 運算子
return null; // 只能回傳 null 或參數本身
}
回傳型別推導為參數共同父類(如 Integer + String → Object)。
public static <T> void swap(T[] arr, int i, int j) {
T tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp;
}
// 正確:swap(new Integer[]{1,2,3}, 0, 1);
// 錯誤:swap(new int[]{1,2,3}, 0, 1); // 基本型別陣列不適用
<T extends Number> void process(T t) { ... } // T 必須是 Number 或其子類
<T super Integer> void consume(T t) { ... } // T 必須是 Integer 或其父類(僅用於通配符)
public static <T> T autoConvert(Object obj) {
return (T) obj; // 編譯器會根據賦值目標推導 T
}
Object obj = "hello";
String s = autoConvert(obj); // T 推導為 String,無需強轉
public static <T> void fillArray(T[] arr, T val) {
for (int i = 0; i < arr.length; i++) arr[i] = val;
}
Integer[] nums = new Integer[3];
fillArray(nums, 99); // 正常
fillArray(nums, "oops"); // 編譯錯誤:String 不能賦值給 Integer[]
<T> void showAndAdd(Collection<T> col, T item) {
col.add(item); // 允許新增
for (T e : col) System.out.println(e);
}
void showOnly(Collection<?> col) {
// col.add(item); // 編譯錯誤:未知型別不可新增
for (Object e : col) System.out.println(e);
}
核心差異:通配符 ?> 代表「未知具體型別」,為安全禁止寫入;泛型 <T> 保留型別資訊,允許寫入。
class Box<E> {
private E data;
public void set(E e) { data = e; }
public E get() { return data; }
}
List<Integer> → List)Vector<Integer> 與 Vector<String> 共用同一份 .class 位元碼void show(Vector<Integer> v) {}
void show(Vector<String> v) {} // 編譯錯誤:擦除後重複
List<T>)而非泛型陣列Class<T> 型別權杖(如 Array.newInstance(clazz, size))? extends T 用於「讀取」(生產者),? super T 用於「寫入」(消費者)— PECS 原則