pecs原则中? extends t用于生产者(只读),? super t用于消费者(只写);src是生产者,只产出t或其子类元素供dest消费。

这个方法签名直接体现了 PECS 原则的核心思想:用 ? extends T 表示“生产者”,用 ? super T 表示“消费者”。
src 是生产者:只读,必须用 ? extends T
源列表 src 的作用是“产出”元素,供 dest 消费。它必须能安全提供类型为 T 或其子类的实例:
-
List extends T>保证每次get()返回的值可以赋给 T(比如Fruit f = list.get(0);合法) - 不允许写入(除 null),因为编译器不知道实际是
List<apple></apple>还是List<orange></orange>,加错类型会破坏类型安全 - 例如:
List extends Number>可以是ArrayList<integer></integer>或LinkedList<double></double>,都能安全读出 Number
dest 是消费者:只写,必须用 ? super T
目标列表 dest 的作用是“接收”元素,它需要能容纳所有来自 src 的 T 类型实例:
-
List super T>保证add(t)总是合法(比如T是Integer,那么List<number></number>和List<object></object>都能接受) - 读取时只能得到
Object,因为 dest 实际可能是List<number></number>或List<object></object>,无法确定更具体的公共类型 - 例如:
List super Integer>允许传入ArrayList<number></number>,也允许传入LinkedList<object></object>
二者配合,实现类型安全的泛型拷贝
整个拷贝逻辑依赖于两者的协同:
- src 生产 T 类型值 → dest 能消费 T 类型值 →
dest.add(src.get(i))在编译期就成立 - 不需要运行时类型检查,也不需要强制转换
- 调用
copy(students, persons)时,Student extends Person,所以students是List extends Person>,persons是List super Student>,完全匹配
PECS 就是读写职责的类型契约
不是语法技巧,而是设计契约:
- 你要从集合里拿东西 → 它得是生产者 → 用
? extends T - 你要往集合里放东西 → 它得是消费者 → 用
? super T - Collections.copy 把这个契约写进了方法签名,让编译器替你把关
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











