? super T 表示集合元素类型为 T 或其任意父类,允许安全写入 T 及其子类实例,读取时只能得到 Object;它拓宽可接受的集合类型,专用于消费者场景,如通用 addAll 工具方法。

Java 中用 ? super T 限制泛型下限,核心是让方法或变量能安全接收类型 T 或其任意父类 的集合,同时只允许向其中写入 T 及其子类 的实例——它不是限制“能写什么”,而是确保“无论实际集合是什么父类型,写进去都一定不越界”。
语法含义:? super T 到底表示什么
? super Integer 不代表“可以写 Integer 的父类”,而是说:这个集合的元素类型是某个未知类型 X,且 X 是 Integer 或它的父类(比如 Number、Object)。编译器只知道 X ≥ Integer,但不知道具体是哪一个。
- 合法指向:
ArrayList<Integer>、ArrayList<Number>、ArrayList<Object> - 非法指向:
ArrayList<Long>、ArrayList<String>(与 Integer 无继承关系)
写入规则:为什么只能 add(T) 和它的子类
因为集合的实际类型可能是 Integer、Number 或 Object 中任意一种,唯一能在所有情况下都安全写入的,就是 T 本身及其子类对象——它们可以被向上转型为任何父类引用。
-
list.add(new Integer(42))✅ 安全(Integer → Integer / Number / Object 都成立) -
list.add(new AtomicInteger(100))✅ 安全(AtomicInteger 是 Integer 子类) -
list.add(new Number())❌ 编译报错(如果实际是 ArrayList<Integer>,Number 就不兼容) -
list.add(new Object())❌ 同理,太宽泛,无法保证类型兼容
读取限制:为什么只能得到 Object
既然编译器只知道元素类型 ≥ T,却不确定具体是哪个父类,那读操作就只能退到最宽泛的安全类型:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
-
Object o = list.get(0);✅ 唯一安全的读法 -
Integer i = list.get(0);❌ 编译错误 -
Number n = list.get(0);❌ 编译错误
这不是缺陷,而是设计选择:下限通配符专为“消费者”场景服务,重点在写,不在读。
典型使用场景:PECS 原则中的 Consumer
当方法要往集合里“放东西”,就该用 ? super T。例如通用的添加工具方法或数据转移:
public static <T> void addAll(List<? super T> dest, List<? extends T> src) {
for (T item : src) {
dest.add(item); // 安全:dest 肯定能装下 T
}
}
- 调用时可传
ArrayList<Number>或ArrayList<Object>作为 dest - src 可以是
ArrayList<Integer>、ArrayList<Double>等 - 这种组合兼顾了灵活性和类型安全

















