在 JDK 源碼(如 Collections.sort())中頻繁出現的 <T extends Comparable<? super T>> 讓許多開發者望而生畏。本文通過對比實驗、代碼演示、PECS 原則,徹底講透這個「最強類型參數」的來龍去脈。
| 聲明 | 含義 | 限制 |
|---|---|---|
<T extends Comparable<T>> | T 必須實現 Comparable<T>,即「T 能與 T 比較」 | 子類若未顯式實現 Comparable<子類>,無法傳入 |
<T extends Comparable<? super T>> | T 實現 Comparable<T> 或 Comparable<T的父類>,即「T 能與 T 或其父類比較」 | 子類繼承父類的 Comparable<父類> 即可傳入,靈活性大增 |
class Animal implements Comparable<Animal> {
int age;
Animal(int age) { this.age = age; }
public int compareTo(Animal other) { return this.age - other.age; }
}
class Dog extends Animal { Dog(int age) { super(age); } } // 未顯式實現 Comparable
// 版本 1:嚴格模式
public static <T extends Comparable<T>> void sort1(List<T> list) { Collections.sort(list); }
// 版本 2:靈活模式(JDK 實際簽名)
public static <T extends Comparable<? super T>> void sort2(List<T> list) { Collections.sort(list); }
public static void main(String[] args) {
List<Animal> animals = Arrays.asList(new Animal(25), new Dog(35));
List<Dog> dogs = Arrays.asList(new Dog(5), new Dog(18));
sort1(animals); // ✓ Animal 實現 Comparable<Animal>
sort1(dogs); // ✗ 編譯錯誤:Dog 未實現 Comparable<Dog>
// 錯誤:The method sort1(List<T>) is not applicable for (List<Dog>)
sort2(animals); // ✓
sort2(dogs); // ✓ Dog 繼承了 Comparable<Animal>,Animal 是 Dog 的父類
}
class Dog extends Animal implements Comparable<Dog> { ... }
// 編譯錯誤:The interface Comparable cannot be implemented more than once with different arguments: Comparable<Animal> and Comparable<Dog>
Java 禁止類直接或間接實現同一泛型接口的不同參數化類型。子類只能 Override 父類的 compareTo(Animal) 方法。
Comparable<T> 的類型參數 T 是消費者角色(compareTo(T other) 消費 T),因此應用 ? super T(下界通配符)。
Comparable<? super T> 表示:比較器能處理 T 及其父類 → 滿足「消費者用 super」。List<Dog> 可傳入要求 Comparable<? super Dog> 的方法,因 Comparable<Animal> 是 Comparable<? super Dog> 的子類型(泛型協變)。
public class java.util.Date implements Comparable<java.util.Date> { ... }
public class java.sql.Date extends java.util.Date { ... } // 繼承 Comparable<java.util.Date>
List<java.sql.Date> 無法傳給 <T extends Comparable<T>> 方法。<T extends Comparable<? super T>> 方法(如 Collections.sort)。
public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp)
<T> 簡單,但在參數中用 ? extends T(生產者)和 ? super T(消費者)擴展。
public TreeSet(Comparator<? super E> comparator)
? super E。| 誤區 | 真相 |
|---|---|
用具體類名替代 T 理解(如 <Dog extends Comparable<Dog>>) | 類型參數會「遮蔽」同名類,導致 The type parameter Dog is hiding the type Dog 警告,且邏輯錯誤 |
以為 List<? extends Animal> 可替代 <T extends Animal> | 前者無法在方法內創建 T、返回 T、多參數關聯 T;後者類型參數可在返回值、方法體、多參數間傳遞 |
| 覺得復雜就不用泛型 | 泛型是編譯期類型安全的基石,掌握 PECS 可寫出極具彈性的 API |
ClassCastException。Comparable 消費元素,故用下界 super。