? super t 用于安全批量添加,允许向 list

用 ? super T 实现安全高效的批量添加,关键不是“能加”,而是“加得准、加得稳、不破坏类型契约”。它解决的不是能不能写的问题,而是让不同层级的集合都能被同一个写入逻辑安全接纳。
明确下限通配符的适用边界
声明为 List super Integer> 的参数,实际可接收:List<integer></integer>、List<number></number>、List<object></object>,但不能接收 List<string></string> 或 List<localdatetime></localdatetime>。编译器只允许向其中添加 Integer 及其子类(如 AtomicInteger),因为所有这些类型天然可赋值给 Integer 的任意父类引用。
- ✅ 合法:
target.add(new Integer(42))、target.add(new AtomicInteger(100)) - ❌ 编译报错:
target.add("abc")、target.add(3.14)、target.add(new Object())(Object不是Integer的子类)
批量添加必须配合泛型方法才真正实用
单独使用 List super T> 做参数虽能接收宽泛类型,但无法在方法体内获知元素具体类型,也就没法做通用遍历。所以真实场景中,它几乎总是和泛型方法结合:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
public <t> void batchAdd(Iterable extends T> src, Collection super T> dest) {
for (T item : src) {
dest.add(item); // 安全:item 是 T,dest 能装下 T 或其父类
}
}</t>
- 调用示例:
batchAdd(intList, numberList)(intList: List<integer></integer>,numberList: List<number></number>) - 也支持:
batchAdd(stringList, objectList)(stringList: List<string></string>,objectList: List<object></object>) - 但不支持:
batchAdd(doubleList, integerList)(类型不兼容,T 推断失败)
读取操作要主动降级,避免强转陷阱
向 List super Integer> 写入是安全的,但从里面读出来只能是 Object。别试图直接强转:
- ✅ 安全读取:
Object o = list.get(0); - ⚠️ 危险强转:
Integer i = (Integer) list.get(0);—— 若实际是List<object></object>,运行时抛ClassCastException - ? 正确做法:如果业务真需按具体类型处理,应在调用方确认容器真实类型,或改用非通配符的明确泛型(如
List<number></number>)
避开三个典型误用
很多问题不是语法错,而是语义错:
- 把
? super T用在只读方法里——它本就不适合读,应换? extends T - 认为
List super Number>能接受Double就也能接受String——错,String和Number无继承关系 - 在接口定义中硬写
void log(List super String>)——通配符应出现在使用处,而非接口契约本身;接口应定义为<t> void log(List<t>)</t></t>或留白由调用方传入通配符
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










