Consumer Super 场景的核心定位是“只负责收数据”,使用 ? super T 可安全向更宽泛类型集合添加元素;它支持构建类型安全的消费管道,但禁止从集合中读取具体类型元素。

Consumer Super 场景的核心定位
当你设计一个只负责“收数据”的方法或组件时,? super T 就是它的自然选择。它不关心集合具体是什么类型,只要能装下 T 或它的子类就行——比如往 List<Object>、List<Number> 或 List<Integer> 里都安全添加 Integer 实例。
封装可复用的数据消费管道
把 ? super T 融入工具方法,能避开强制转换、避免类型擦除,让调用方自由传入更宽泛的目标容器:
- 定义通用添加方法:
public static <T> void consumeAll(Collection<? super T> target, Iterable<T> source) - 内部直接遍历
source并调用target.add(item),无需任何类型检查或转型 - 调用示例:
consumeAll(numbers, integers)(numbers是List<Number>,integers是Iterable<Integer>)
配合 extends 构建端到端流转链
真实业务中,消费往往不是孤立的。上游输出用 ? extends T,下游接收用 ? super T,就能形成类型安全的流水线:
- 例如复制工具:
public static <T> void copy(List<? extends T> src, List<? super T> dest) - 支持
copy(students, people)(Student → Person)、copy(people, objects)(Person → Object) - 编译器全程校验:src 拿出的是 T,dest 能接住 T,中间不丢失类型语义
注意读取限制,明确使用边界
? super T 的代价是读取能力受限——从里面取元素只能当 Object 用:
- 不要写
String s = list.get(0),即使你知道它其实是String - 如果后续必须强转,说明设计意图已偏离 Consumer 定位,应考虑拆分逻辑或改用具体泛型
- 真正高效的数据消费管道,重点在“写得稳、接得广”,而不是“读得细”

















