? super T 是下界通配符,表示集合可接受 T 或其任意父类实例,支持安全写入但读取只能返回 Object;例如 List<? super Integer> 可 add(Integer),但 get() 结果只能赋给 Object。

Java 中利用通配符下限(? super T)实现“只写集合”的数据注入,核心是让方法能安全地往类型更宽泛的集合中添加子类对象,同时放弃对读取结果做精确类型保证——这是泛型类型安全的设计取舍,不是限制,而是保护。
什么是 ? super T:下界通配符的本质
它表示“这个集合能接受 T 类型或其任意父类 的实例”,例如:
-
List<? super Integer>可以是List<Integer>、List<Number>或List<Object> - 你一定能向其中
add(Integer),因为 Integer 在所有这些类型中都是合法元素 - 但调用
get(0)时,返回值只能赋给Object(最顶层公共父类),无法直接当Number或Integer用
为什么只适合“写入”,不适合“读取”
下界通配符放宽了写入约束,但收紧了读取能力:
-
add()安全:只要传入的是T或其子类(如Integer),就一定兼容所有? super T所代表的具体类型 -
get()不安全:集合实际可能是List<Object>,里面存了 String、Date 等任意对象,编译器无法保证取出的就是T - 所以编译器只允许把
get()结果当作Object处理,避免运行时ClassCastException
实战写法:定义一个通用写入工具方法
比如批量把 BigDecimal 写入不同层级的数字集合:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
public static void addBigDecimals(List<? super BigDecimal> target, BigDecimal... nums) {
for (BigDecimal n : nums) {
target.add(n); // ✅ 编译通过,运行安全
}
}
调用示例:
-
addBigDecimals(new ArrayList<BigDecimal>(), bd1, bd2);→ 合法(BigDecimal是自身的父类) -
addBigDecimals(new ArrayList<Number>(), bd1, bd2);→ 合法(BigDecimal是Number子类) -
addBigDecimals(new ArrayList<Object>(), bd1, bd2);→ 合法(BigDecimal是Object子类) -
addBigDecimals(new ArrayList<String>(), bd1);→ ❌ 编译失败(String不是BigDecimal的父类)
常见误区澄清
别混淆这几个概念:
-
super关键字 ≠? super T:前者用于调用父类构造器或方法,和泛型类型无关 - 不能写
List<super BigDecimal>:语法错误,super不能出现在尖括号内 - 不是“向下转型”或“强制注入”:它是编译期类型检查机制,靠通配符声明表达意图,不靠运行时转换
- 不解决历史非泛型集合问题:像
ArrayList(无泛型)本身就能存任意对象,无需通配符;? super T是为增强泛型安全性而设

















