PECS原则核心是按操作判断:只读用? extends T(生产者,可取不可存),只写用? super T(消费者,可存不可精准取),读写兼具则不用通配符而用具体泛型。

记住 PECS 的关键不是背口诀,而是盯住变量在当前代码里“干啥用”。它本质是操作导向的判断——你对这个泛型容器,是在往外拿数据,还是往里塞数据?
只读就用 ? extends T(生产者)
当你从集合中取元素、遍历、调用 get()、iterator().next(),且不打算 add 或 set 任何东西时,它就是“生产者”。
- ✅ 安全:取出的对象能当 T 用(比如 List extends Number> 取出的可以调 doubleValue())
- ❌ 禁止:不能 add 任何具体对象(连 new Number() 都不行),因为编译器不知道底层是 Integer 还是 Double
- ? 记忆锚点:“Extends = Expose(暴露出来)”,它把 T 或子类暴露给你读
只写就用 ? super T(消费者)
当你向集合里 add、addAll、collect 输入数据,且基本不读、或读出来也只当 Object 处理时,它就是“消费者”。
- ✅ 安全:可以放心 add 所有 T 及其子类(比如传入 Apple 到 Collection super Fruit>)
- ❌ 禁止:get(0) 结果只能接成 Object,不能直接强转为 T(实际可能是 Collection
- ? 记忆锚点:“Super = Swallow(吞进去)”,它能吞下 T 和所有更宽泛的类型
读写都做,就别用通配符
如果方法既要 get 又要 add,比如交换两个位置、批量更新、自定义排序等,通配符会锁死读或写能力。这时直接用泛型方法或具体类型更清晰安全。
立即学习“Java免费学习笔记(深入)”;
- ✔ 推荐写法:public
void swap(List list, int i, int j) - ❌ 避免硬凑:void bad(List extends T> list) —— 写不了;void bad(List super T> list) —— 读不准
看方法签名,三秒定位角色
快速判断技巧:扫一眼参数类型和方法体里主要操作。
- 参数是 List extends Fruit>,方法里只有 for-each 和 getName() → 生产者 → 正确
- 参数是 Collection super Apple>,方法里反复 add(new Fuji()) → 消费者 → 正确
- 参数是 List>,方法里又 get 又 add → 模糊意图 → 改用 List


















