List extends Fruit> list = new ArrayList(); // 假設 Apple extends Fruit
list.add(new Apple()); // 編譯錯誤!
list.add(new Fruit()); // 編譯錯誤!
list.add(null); // 唯一允許
List super Fruit> list2 = new ArrayList(); // Food 是 Fruit 父類
list2.add(new Fruit()); // ✓ 允許
list2.add(new Apple()); // ✓ 允許 (Apple 是 Fruit)
list2.add(new Food()); // ✗ 編譯錯誤 (實際可能是 List)
Fruit f = list2.get(0); // ✗ 返回 Object,需強轉
書籍正確。**`List extends Fruit>` 禁止任何非 null 的 `add` 操作**,因為無法保證運行時類型兼容。你的測試代碼若「能放」,可能是:
| 場景 | 聲明 | 操作 |
|---|---|---|
| 方法只讀取元素 | `void print(List extends Fruit> list)` | `for(Fruit f: list) ...` |
| 方法只寫入元素 | `void addFruits(List super Fruit> list)` | `list.add(new Apple());` |
| 既讀又寫 | `void process(List | 無通配符,具體類型 |
List是 List extends Fruit> 的子類型 (協變 Covariant) List 是 List super Apple> 的子類型 (逆變 Contravariant) List 不是 List 的子類型 (不變 Invariant)
Java 泛型**預設不變**,通配符提供受限協變/逆變能力。