返回 list

公共接口的返回值应明确、稳定、可预测,而 ? extends T 会削弱调用方对类型的实际掌控力,违背接口契约的设计初衷。
为什么返回 List extends Number> 是危险的
它告诉调用方:“我给你一个元素是 Number 或其子类的列表”,但没说明具体是哪种子类。调用方无法安全地向该列表添加任何非 null 元素(编译拒绝),也无法直接转型使用(比如想当作 List<integer></integer> 处理时会失败)。这导致返回值“只读但不可复用”,徒增理解成本和防御性检查。
- 调用方无法做
list.add(...)—— 即使逻辑上合理也不被允许 - 无法用
instanceof或泛型类型判断来分支处理,因为运行时无泛型信息 - 若后续实现改为返回
List<double></double>,调用方代码仍能编译通过,但语义已悄然变化,易埋隐患
更合理的替代方案
优先返回具体泛型类型,或用类型参数抽象化,而非通配符隐藏细节。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 返回
List<number></number>:如果业务上确实允许混合类型(如整数与浮点数共存),就明确声明,调用方可自由读写 - 用方法级泛型:
<t extends number> List<t> getNumbers()</t></t>—— 让调用方决定类型变量,保持类型一致性 - 定义专用返回类型:
NumberList或ImmutableNumberList封装行为,比裸通配符更具语义和约束力
例外情况:仅当“只读 + 类型无关”是核心需求时才考虑
例如工具类中提供通用聚合结果,且明确不希望调用方修改或依赖具体子类型:
-
Collections.unmodifiableList(List extends E> list)这类标准库方法,本质是防御性包装,不是业务接口设计范式 - 框架回调接口中,若生产者只负责交付、消费者只负责消费(如事件总线 payload),
? extends Event可接受,但仍建议配合 sealed class 或明确子类型枚举提升可维护性
根本原则:接口是契约,不是谜题
返回值类型应让调用方一眼看懂能做什么、不能做什么。通配符 ? extends T 把类型不确定性推给使用者,增加了误用风险和调试难度。架构设计中,清晰胜于灵活,稳定优于泛化。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










