通配符是解决Java泛型无继承关系限制的关键,通过?、? extends T、? super T实现多态式传参:?用于只读操作,? extends T支持安全读取,? super T支持安全写入,结合接口多态达成类型安全与集合复用。

Java 中泛型配合多态在方法形参中传递带通配符的集合,核心在于用通配符突破泛型“无继承关系”的限制,让不同具体类型的集合能被统一接口接收,同时保持类型安全。
为什么需要通配符来支持多态式传参
泛型本身不具备多态性:List<String> 不是 List<Object> 的子类型,哪怕 String 是 Object 的子类。直接写 void process(List<Object> list) 无法接收 List<String> 或 List<Integer>,编译报错。通配符(?)及其限定(? extends / ? super)正是为解决这一矛盾而设计的“类型适配器”。
三种通配符在形参中的典型用法
?(无界通配符):适用于只读且不关心具体元素类型的操作
- 形参声明:
void printAll(List<?> list) - 可传入:
List<String>、List<Date>、List<User>等任意泛型列表 - 方法内只能调用
get()(返回 Object)、size()、isEmpty()等与类型无关的方法 - 不能调用
add()(编译错误),因为编译器无法确认该往里加什么类型
? extends T(上界通配符):适用于“消费数据”场景,强调类型安全性读取
立即学习“Java免费学习笔记(深入)”;
- 形参声明:
void sumNumbers(List<? extends Number> numbers) - 可传入:
List<Integer>、List<Double>、List<BigDecimal> - 方法内可安全调用
get(),返回值自动提升为Number类型,支持统一处理 - 不能调用
add()(除null外),因不确定底层实际是 Integer 还是 Double 列表
? super T(下界通配符):适用于“生产数据”场景,强调向集合写入的能力
- 形参声明:
void addInts(List<? super Integer> target) - 可传入:
List<Integer>、List<Number>、List<Object> - 方法内可安全调用
add(new Integer(42))或add(100)(自动装箱) - 但
get()返回的是Object,需手动转型,无法保证具体类型
结合接口多态的实际示例
定义一个泛型处理器接口:
interface Processor<T> {
void handle(T item);
}
实现多个子类:
class StringPrinter implements Processor<String>class NumberLogger implements Processor<Number>
再设计一个通用调度方法:
public static <T> void dispatch(List<? extends T> items, Processor<T> processor) {
for (T item : items) {
processor.handle(item); // 多态调用,且类型安全
}
}
调用时:
-
dispatch(stringList, new StringPrinter())✅ -
dispatch(intList, new NumberLogger())✅(Integer 是 Number 子类)
这里既利用了泛型约束类型边界,又通过通配符使形参具备接收多种具体泛型集合的能力,真正实现了“面向接口编程 + 类型安全 + 集合复用”三者的协同。


















