pecs原则是java泛型中指导通配符使用的经验法则:只读用? extends t(生产者),只写用? super t(消费者),读写并存则用具体类型;它仅在编译期保障类型安全,不改变运行时行为。

PECS 原则是 Java 泛型中指导通配符使用的核心经验法则,它不改变运行时行为,只在编译期保障类型安全。理解的关键在于:**看泛型参数在方法中是“往外吐数据”还是“往里收数据”,而不是看它声明的类型本身。**
只读场景:用 ? extends T(生产者)
当方法仅从集合中获取元素、不添加新内容时,该集合就是“生产者”。? extends T 表示容器里装的是 T 或其任意子类,因此取出的每个元素都能安全当作 T 使用。
- ✅ 允许操作:遍历、get()、调用 T 定义的方法(如 doubleValue())
- ❌ 禁止操作:add()、set()(除 null 外),因为编译器无法确认实际类型是 Integer 还是 BigDecimal
- 典型例子:void printAll(List extends Number> nums) 可接收 List
、List ,内部统一按 Number 处理
只写场景:用 ? super T(消费者)
当方法只向集合中添加元素、不依赖读出的具体类型时,该集合就是“消费者”。? super T 表示容器能装 T 或其任意父类,因此任何 T 实例都能安全写入。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- ✅ 允许操作:add(T)、addAll(Collection extends T>)
- ❌ 禁止操作:把 get(0) 直接当 T 用——返回类型是 Object,强转可能抛 ClassCastException
- 典型例子:void addIntegers(List super Integer> target) 可传入 List
、List 或 List
读写并存:不用通配符,直接用具体类型
如果一个参数既被遍历又被添加元素,说明它承担双重角色。此时通配符会限制合法操作或破坏类型安全。
- ❌ 避免:void process(List extends String> list) 再调用 list.add("x") —— 编译失败
- ✅ 推荐:void process(List
list) —— 类型明确,读写自由 - JDK 实践:Collections.copy(dest, src) 拆成两个参数,dest 是 ? super T(只写),src 是 ? extends T(只读)
常见误区提醒
PECS 不是泛型继承规则,也不影响运行时。List extends Fruit> 不是 List
- 对 final 类(如 String)用 ? extends String 语法合法但无意义,因无子类,等价于 String
- 试图在 ? extends T 集合里 add() 是编译期主动拦截,不是 bug,而是类型安全设计
- 把 ? super T 的 get() 结果直接强转为 T,需先做 instanceof 检查,否则运行时风险高
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










