? super t 表示集合元素类型为t或其父类,故可安全写入t及子类对象(因t兼容所有可能实际类型),但读取时只能视为object以确保类型安全。

泛型下限通配符(? super T)允许向集合中写入 T 类型或其子类型 的对象,但不能安全地读取具体类型(只能当作 Object 读)。对 ArrayList super String> 这类声明,你可以写入 String 或它的子类实例(如 ""、new StringBuilder().toString()),但不能写入 Object 或 Integer 等非 String 子类型的对象。
为什么只能写入 T 及其子类?
下限通配符表示“某个未知的、String 的父类或自身”,比如可能是 ArrayList<object></object>、ArrayList<charsequence></charsequence>、ArrayList<string></string>。只要写入的是 String(或其子类),它就一定兼容所有这些可能的实际类型——因为 String 是它们的子类型或自身。
-
String可以放进ArrayList<string></string>✅ -
String可以放进ArrayList<charsequence></charsequence>✅(String 实现 CharSequence) -
String可以放进ArrayList<object></object>✅(String 是 Object 子类) - 但
Object不能放进ArrayList<string></string>❌ —— 所以不允许写入Object
正确写入方式示例
假设你有一个方法接受下限通配符参数:
public static void addStrings(List super String> list) {
list.add("hello"); // ✅ 合法:String 是 ? super String 的子类型
list.add(new String("hi")); // ✅ 合法
// list.add(new Object()); // ❌ 编译错误:Object 不一定是 String 的子类
}
调用时可以传入多种实际类型:
addStrings(new ArrayList<string>());</string>addStrings(new ArrayList<object>());</object>addStrings(new ArrayList<charsequence>());</charsequence>
不能安全读取具体类型
虽然你能往里写 String,但读出来只能当 Object 处理:
List super String> list = new ArrayList<object>();
list.add("abc");
Object obj = list.get(0); // ✅ OK
// String s = list.get(0); // ❌ 编译错误:无法确定返回的是不是 String
</object>
这是因为底层实际类型可能是 ArrayList<object></object>,里面可能混入了其他对象(比如你之前手动加过 new Object()),编译器不保证类型安全。
常见误区提醒
- 误以为
? super String表示“能装 String 和它的父类”——其实它表示“这个 List 的元素类型是 String 的某个父类(或 String 自身)”,重点在容器类型未知但有下界 - 试图从
List super T>中强转取值,容易运行时 ClassCastException - 混淆上限(
? extends T)和下限:前者适合读,后者适合写(PECS 原则:Producer Extends, Consumer Super)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











