? super T 支持安全写入 T 及其子类对象,因实际类型为 T 或其父类,T 可向上转型;读取时只能得到 Object,需强制转换,遵循 PECS 原则中 Consumer 用 super 的设计。

在 Java 中,使用 ? super T 通配符时,你可以安全地向集合写入类型为 T 或其子类的对象,但不能从中读取具体类型(只能读为 Object)。关键在于:**下界通配符的设计目的就是支持“写入”,而非“读取”**。
理解 ? super T 的写入能力
? super T 表示该泛型参数是 T 的某个**父类型(含 T 自身)**。由于所有 T 实例都兼容其任意父类型,因此往其中添加 T 类型对象是类型安全的。
- 例如:
List super Integer>可能实际是List<integer></integer>、List<number></number>或List<object></object> - 无论它底层是什么,
Integer都能被合法加入这三者中的任意一个 - 但你无法确定从里面取出的是
Integer还是Number还是Object,所以读取时只能当作Object
正确写入的具体写法
直接调用 add() 方法传入 T 或其子类实例即可 —— 编译器会校验是否满足下界约束。
- ✅ 允许:
list.add(new Integer(42));、list.add(100);(自动装箱为Integer) - ✅ 允许:
list.add(new AtomicInteger(1));?不行 ——AtomicInteger不是Integer的子类,而是同级类,不满足T类型要求 - ❌ 禁止:
list.add(new Object());——Object不一定是Integer的父类(虽然它是,但编译器只信任明确的T及其子类);更关键的是,Object超出了T的范围,可能破坏类型安全
常见误用与规避方式
容易出错的地方是试图“先读再写”或混淆上界/下界用途:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 不要对
? super T做类型强转读取:(Integer) list.get(0)编译不通过,且运行时可能 ClassCastException - 不要用
? super T替代具体类型做复杂操作 —— 它适合工具方法中统一接收“能接受T的容器”,比如void copy(List super Integer> dest, List<integer> src)</integer> - 如果既要读又要写,就别用通配符,改用具体类型或类型变量:
<t> void process(List<t> list)</t></t>
实用例子:一个安全的写入工具方法
下面是一个典型应用:把一组 Integer 添加到任意能接受它们的列表中:
public static void addIntegers(List<? super Integer> target, Integer... values) {
for (Integer v : values) {
target.add(v); // ✅ 安全写入
}
}
调用时可传入:ArrayList<number></number>、LinkedList<object></object>、甚至 ArrayList<integer></integer>,全部合法。

















