? super T 用于安全写入T及子类实例并限制读取为Object,遵循PECS原则中Consumer用super的规范,适用于add、accept等消费场景。

Java 中使用 ? super T 是为了安全地向泛型容器写入数据,核心是“限制读、放开写”——它不扩大你能读到的类型,但明确允许你写入 T 及其子类实例。
写入时只认 T 及其子类,其他一律拒绝
声明为 List super Integer> 的变量,可指向 List、List 或 List。编译器确认:无论底层实际是什么,Integer 总能装进去。
- ✅ 允许:
list.add(42)、list.add(new AtomicInteger(1)) - ✅ 允许:
list.add(null)(所有引用类型都支持) - ❌ 禁止:
list.add("hello")(String 和 Integer 无继承关系) - ❌ 禁止:
list.add(new Object())(Object 不是 Integer 的子类,不能保证放进List安全)
读取只能用 Object 接收,不可强转
因为实际类型可能是 Object、Number 或 Integer,编译器无法推断统一返回类型。
- ✅ 安全:
Object obj = list.get(0); - ❌ 编译失败:
Integer i = list.get(0);、Number n = list.get(0); - ⚠️ 若真要转,必须显式强制转换,并自行处理
ClassCastException
典型应用场景:通用写入工具方法
当方法目标是“接收并存入数据”,就该用 ? super T。
- 集合复制:
public staticvoid copy(List extends T> src, List super T> dest) - 批量添加:
public static void addAll(List super String> target, String... items) - 函数式接口参数:
Consumer super String>可安全接受String,也可用于更宽泛的Object处理器
牢记 PECS 原则:Consumer 用 super
别记混:? super T 是为“消费者”设计的——它消费 T 类型的数据(比如 add、accept、write)。如果泛型参数是用来往外拿数据(如 get、iterator),那就该用 ? extends T。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











