? super T 表示泛型类型为 T 或其任意父类,用于安全写入 T 类型对象;可向 List<? super Integer> 添加 Integer,但 get() 仅返回 Object,体现 PECS 中“Consumer Super”原则。

Java 中的下限通配符 ? super T 并不是“限制父类类型”,而是**允许泛型参数取 T 或其任意父类(包括 T 本身)**。它的作用是放宽类型约束,让方法能接受更宽泛的集合类型,但前提是保证写入安全。
它怎么定义下界:语法与含义
? super Integer 表示“某个未知类型,但它至少是 Integer 或它的父类”。也就是说,这个通配符匹配:
-
List<Integer>(T 本身) -
List<Number>(Integer 的直接父类) -
List<Object>(Number 的父类,也是 Integer 的祖先) -
List<Serializable>、List<Comparable<?>>等所有 Integer 实现的接口类型(只要它们是 Integer 的父类型)
它为什么只允许写入 T,不能安全读取?
因为编译器只知道“元素类型 ≥ T”,但不确定具体是哪一个父类。例如:
- 你传入
List<Number>,get(0)返回Number - 你传入
List<Object>,get(0)返回Object - 编译器无法统一返回类型,所以统一按最顶层的公共父类
Object处理
所以:list.add(new Integer(42)) 总是合法;但 Integer i = list.get(0) 编译失败,必须写成 Object o = list.get(0)。
立即学习“Java免费学习笔记(深入)”;
它在方法设计中怎么体现“限制父类”?
这种“限制”其实是对**实参类型范围的声明**,不是运行时检查。比如:
public static <T> void copyTo(List<? super T> dest, List<T> src) {
for (T item : src) {
dest.add(item); // ✅ 安全:dest 肯定能装下 T
}
}
调用时:
-
copyTo(new ArrayList<Number>(), intList)→ 合法 -
copyTo(new ArrayList<Object>(), intList)→ 合法 -
copyTo(new ArrayList<String>(), intList)→ 编译报错(String 不是 Integer 的父类)
这里 ? super Integer 就是在告诉编译器:“只接受 Integer 及其父类的集合”,这就是它对父类类型的“限制”逻辑。
常见误区:super 关键字 ≠ ? super T
super 是子类中调用父类构造器或方法的关键字,和泛型通配符无关。你不能写 List<super Integer>,那是语法错误。真正起作用的是 ? super Integer 这个整体符号,其中 super 只是关键字标记,表示“下界”,不参与继承调用。


















