? super T 保证写入安全,因其表示类型为T或其父类,允许添加T及子类实例且禁止无关类型;读取时只能获Object,需强制转换;遵循PECS原则:Consumer用super,Producer用extends。

Java 泛型中使用 ? super T 实现安全的下界写入,核心在于:它让编译器确认“目标容器至少能装下 T 类型的对象”,从而允许你向其中添加 T 或其子类实例,同时杜绝类型污染风险。
为什么 ? super T 能保证写入安全
因为 ? super T 表示实际类型是 T 本身或它的任意父类(比如 Object、Number、Animal)。而 T 及其所有子类对象,天然可以赋值给这些父类引用——这是 Java 继承体系的基本规则。编译器据此验证:只要传入的是 T 类型(如 Integer),无论底层实际是 List<integer></integer>、List<number></number> 还是 List<object></object>,add() 都不会出错。
- ✅ 允许:
list.add(new Integer(42))、list.add(new Long(100L))(若 T 是Number) - ❌ 禁止:
list.add(new String("x"))(类型无关,编译直接报错) - ⚠️ 注意:
list.add(new Object())也不允许——因为实际类型可能是List<number></number>,而Object不是Number的子类
典型写法与调用方式
常见于通用工具方法,目标是“消费”数据:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 声明方法参数为
List<? super Integer>,就能接收List<Integer>、List<Number>、List<Object> - 方法体内可放心调用
target.add(value),value 必须是Integer或其子类(如AtomicInteger) - 不能写成
List<? super Number>却往里加Double——除非Double是Number的子类(它是),但必须严格匹配下界类型
读取时只能得到 Object
由于实际类型不确定(可能是 Object,也可能是 Serializable),编译器无法推断统一的返回类型,所以:
立即学习“Java免费学习笔记(深入)”;
- ✅ 安全:
Object obj = list.get(0); - ❌ 编译失败:
Integer i = list.get(0);、Number n = list.get(0); - 如果真需要转回具体类型,必须显式强制转换,并自行承担
ClassCastException风险
牢记 PECS 原则
Producer-Extends, Consumer-Super —— 当泛型参数是用来“收数据”的(比如 add、accept、write),就用 ? super T;如果是“发数据”的(比如 get、iterator、read),就该用 ? extends T。混淆两者会导致编译错误或运行时异常。

















