collections.copy方法体现pecs原则:src为生产者(? extends t),dst为消费者(? super t),签名明确界定读写边界。

Java中Collections.copy方法是PECS原则最典型、最干净的落地体现——它不靠文档解释,而是用方法签名本身把“谁读、谁写、读什么、写到哪”全说清楚。
src 是生产者: extends T> 保证安全读取
源列表声明为 List extends T>,意味着它只负责“产出”T或其子类的实例:
- 可以安全遍历并取出每个元素,编译器保证它们都能向上转型为T(比如从
List<apple></apple>读出的一定是Fruit或其子类) - 禁止调用
add()(除null),因为底层可能是List<apple></apple>也可能是List<banana></banana>,写入任意具体子类都可能破坏类型一致性 - 这种设计解耦了调用方:传
List<student></student>、List<person></person>甚至List<object></object>(若T是Object)都合法,只要元素能当T用
dest 是消费者: super T> 保证安全写入
目标列表声明为 List super T>,意味着它只负责“接收”T或其子类的实例:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 可以安全调用
set(i, element)或add(element),因为T一定能放进List<t></t>、List<object></object>甚至List<serializable></serializable>(只要T实现该接口) - 读取操作受限:从
dest.get(i)只能得到Object,不能直接当T用——这不是缺陷,而是明确告诉调用方:“我这里装得宽,但取出来时你得自己判断” - 这种设计让目标容器更包容:一个
ArrayList<object></object>或LinkedList<serializable></serializable>都能作为dest接收String、Integer等T实例
二者成对出现,构成类型安全的数据管道
PECS不是孤立规则,而是一组协作契约:
-
src产出的每个元素,类型上属于T及其子类;dest声明能容纳T及其父类——两者交集就是T,确保“产”和“消”在类型层面严丝合缝 - 整个复制过程无需强制转换、不抛
ClassCastException、不依赖运行时类型检查,所有安全性由编译器静态验证 - 典型调用如
copy(students, people)(Student→Person)、copy(employees, objects)(Employee→Object)全部通过,且语义清晰
实际使用时的关键约束
签名再精妙,也绕不开运行时前提:
- dest必须预先具备足够容量(长度 ≥ src.size()),否则抛
IndexOutOfBoundsException - dest不能是不可变列表(如
Arrays.asList()返回的固定大小列表),否则set()会抛UnsupportedOperationException - 它只适用于List,不支持Set/Map等其他集合——因为copy本质是按索引覆盖,依赖有序+可随机写
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










