应使用 ? extends T,因为集合作为生产者只输出 T 或其子类实例,需用上界约束确保 get() 元素可安全赋值给 T,但禁止 add() 非 null 值以维护类型安全。

当集合作为数据源(只读、向外提供元素)时,应使用 ? extends T,这是 PECS 中 “Producer Extends” 的直接体现。
为什么必须用 ? extends T
因为集合是“生产者”,它的职责是输出 T 类型或其子类的实例。编译器需要确保从集合中 get() 或遍历时拿到的对象能安全地当作 T 使用——这靠 extends 提供上界约束来保证。
-
List extends Number>可以接收List、List等,所有元素都能赋值给Number变量 - 但不能往里面
add()任何非null值,因为编译器不知道实际类型是Integer还是Double,写入会破坏类型安全
典型使用场景
适用于所有“只取不存”的方法参数或返回类型:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 打印集合内容:
void print(List extends Fruit> fruits) - 计算总和:
double sum(List extends Number> numbers) - 查找最大值:
> T max(List extends T> list)
常见误用与纠正
容易混淆的是把“能装 T 的子类”等同于“能往里加 T 的子类”。实际上:
- ✅ 正确:
List extends Fruit> src = new ArrayList(); Fruit f = src.get(0); - ❌ 错误:
src.add(new Apple());—— 编译失败,类型不确定 - ⚠️ 注意:
src.add(null);是唯一允许的写操作
对比 ? super T 更容易理解
如果这个集合还要接收外部数据(比如往里塞苹果),那它就不是纯生产者,而是消费者,此时该用 ? super Fruit。但只要逻辑明确“只读”,extends 就是唯一安全且符合语义的选择。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










