上限通配符 ? extends t 的核心作用是放宽读取能力、收紧写入权限——它允许安全接收任意 t 的子类型集合,但只允许以 t 类型读取元素,禁止添加(除 null 外)。

上限通配符 ? extends T 的核心作用是**放宽读取能力、收紧写入权限**——它让方法或变量能安全接收任意 T 的子类型集合,但只允许以 T 类型读取元素,禁止添加(除 null 外)。
为什么只能读、不能写
编译器只知道容器里装的是“某个未知的 T 子类”,比如 List extends Number> 可能是 List<integer></integer>,也可能是 List<double></double>。若允许 add(new Integer(1)),而实际容器是 Double 列表,就会破坏类型契约。所以编译器直接禁用所有 add、set 等写入操作。
-
get(i)返回类型是T(如Number),可赋值给T或其父类(Object、Serializable) -
add(E)、set(int, E)全部编译报错,哪怕传入T的实例也不行 -
add(null)是唯一被允许的写入操作,但通常无业务意义
典型读取场景与写法
它天然适配“只进不出”的数据处理逻辑,常见于工具方法设计:
- 聚合计算:求和、平均值、最大值等,只要能调用
T定义的方法即可 - 遍历打印:不关心具体子类,只需统一按
T处理 - 只读校验:如检查是否全为正数、是否有序等
示例:
public double sum(List extends Number> list) {
return list.stream().mapToDouble(Number::doubleValue).sum();
}
该方法可接受 List<integer></integer>、List<bigdecimal></bigdecimal>、List<float></float>,无需重载,且返回值类型明确为 double。
搭配泛型方法提升灵活性
单独用 ? extends T 会限制写入,但结合泛型方法参数,就能在读取后做进一步处理:
- 声明带边界的泛型方法:
<t extends comparable>> T max(List extends T> list)</t> - 利用
T推断出具体可比较类型,既支持List<string></string>也支持List<localdate></localdate> - 内部仍用
? extends T接收,保证输入兼容性;返回值是确定的T,而非模糊的上界
常见误区提醒
注意几个容易踩坑的点:
- 不能把
get()结果直接强转成某个子类(如(Integer) list.get(0)),除非加instanceof检查 - 不能用作方法返回值类型(如
List extends Number> getNumbers()),否则调用方无法安全添加元素 - 不要在类定义中滥用,比如
class Container extends Number>是非法语法——通配符只用于使用位置(参数、变量、返回值),不用于类型声明
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











