? extends T 表示只读集合,元素可安全读为上界类型T(如Number),但除null外禁止写入,因其具体子类型未知,写入可能破坏类型安全,符合PECS中的“Producer”原则。

? extends 的核心限制是只读不写
声明为 Collection<? extends Number> 的集合,表示它装的是某个具体但未知的 Number 子类型,比如可能是 Integer、也可能是 Double,甚至可能是未来新增的 BigDecimal——编译器只知道上限是 Number,却无法确认到底是哪一个。
读取时自动向上转型为上界类型
正因为具体子类型不确定,Java 允许你安全地把每个元素当作上界类型来读取。例如:
-
for (Number n : list)合法 —— 每个元素都能被当作Number使用 -
Number first = list.get(0)合法 —— 返回值类型被推断为Number -
first.doubleValue()合法 —— 可调用Number定义的方法
禁止写入的具体原因
写入操作会被编译器直接拒绝(除 null 外),因为这会破坏类型一致性:
-
list.add(new Integer(42))❌ 不允许 —— 如果实际容器是ArrayList<Double>,加Integer就会出错 -
list.add(new Double(3.14))❌ 同样不允许 —— 实际容器也可能是ArrayList<Integer> -
list.add(null)✅ 唯一允许的写入 ——null是所有引用类型的合法值
这种设计对应 PECS 原则中的 “Producer” 场景
当你把一个泛型集合当作“生产者”(只往外提供数据)使用时,? extends T 是最自然的选择:
立即学习“Java免费学习笔记(深入)”;
- 方法签名如
void printValues(Collection<? extends Number> src)能接收List<Integer>、Set<Double>等任意子类型集合 - 内部可统一按
Number处理,无需重复写多个重载 - 不开放写入口,从源头避免运行时
ClassCastException


















