跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

通配符在方法参数中的应用_通配符如何提升API的灵活性以兼容更多泛型变量

通配符解决泛型不变性导致的类型兼容问题:无界?用于只读操作;? extends T用于生产者(读取T或其子类);? super T用于消费者(写入T或其父类);遵循PECS原则。 通配符在方法参数中主要解决泛型“不变性”带来的类型兼容问题。Java 中
List
不是
List 的子类型,哪怕
String
Object
的子类——这导致很多直觉上合理的调用会编译失败。通配符通过放宽类型约束,让方法能安全地接受更宽泛的泛型实参,从而提升 API 的通用性和复用性。 无界通配符 ?:只读场景下的通用入口 当你只需要遍历、检查或消费集合内容,不关心具体元素类型时,
?
是最轻量的选择。 方法签名示例:
public void printAll(List list)
可传入
List
List
List
等任意类型列表 内部只能把元素当作
Object
处理,不能调用
add()
(除
null
外),因为编译器无法确认实际类型 适合日志打印、统计大小、判空等与类型无关的操作 上界通配符 ? extends T:作为“生产者”时放宽输入 当方法从泛型结构中**读取**数据,并期望这些数据是某个类型的实例(或其子类)时,用
? extends T
。 典型场景:计算总和、查找最大值、批量转换 示例:
double sum(List numbers)
可接收
List
List
List
可以安全地将每个元素当作
Number
使用(如调用
doubleValue()
) 但不能向该列表中添加任何元素(包括
Number
或其子类),因为实际类型可能是
List
,加
Double
会破坏类型安全 下界通配符 ? super T:作为“消费者”时拓宽写入目标 当方法需要向泛型结构中**写入**数据,且只要求目标容器能容纳某类型或其父类时,用
? super T
。 典型场景:批量添加、归并、收集结果 示例:
void addIntegers(List dst)
可接收
List
List
List 可以安全地
add(new Integer(42))
,因为所有这些目标类型都声明能存下
Integer
但从该列表中读出的元素只能当作
Object
使用(因上界未知),无法直接调用
intValue()
遵循 PECS 原则,避免误用 Producer-Extends, Consumer-Super —— 这是判断用哪个通配符的核心口诀。 参数用于“往外拿数据”(生产者)→ 用
? extends T
参数用于“往里塞数据”(消费者)→ 用
? super T
如果既要读又要写,就别用通配符,保持精确类型(如
List
) 返回值类型一般不用通配符(如避免
List
),否则调用方难以处理,应返回明确泛型如
List

相关文章