java泛型通配符用?实现类型安全下的参数灵活传递:只读用? extends t,只写用? super t,纯通用操作用?,遵循pecs原则(producer extends, consumer super)。

Java 泛型通配符用问号(?)实现灵活传参,核心不是“放宽限制”,而是**在类型安全前提下扩大方法可接收的泛型实参范围**。关键在于根据操作意图选对通配符形式:只读、只写,还是纯通用。
只读场景用 ? extends T(上界通配符)
当你只需要从集合中读取元素,并把它们当作 T 或其父类来使用时,这是最安全的选择。
- 声明形如
List extends Number>,可接收List<integer></integer>、List<double></double>、List<number></number> - 能调用
get(),返回值可直接赋给Number类型变量,例如:Number n = list.get(0); - 不能调用
add()—— 编译器无法确认你加的对象是否属于该未知子类型,比如往List extends Number>里加Float,而实际是List<integer></integer>就会破坏类型安全
只写场景用 ? super T(下界通配符)
当你主要向集合中添加 T 类型对象,且希望目标容器类型更宽泛(比如能接受父类或 Object 容器)时,必须用这个。
- 声明形如
List super Integer>,可接收List<integer></integer>、List<number></number>、List<object></object> - 能安全调用
add(new Integer(42)),因为Integer是所有这些类型的子类或本身 - 读取时只能按
Object处理,例如:Object o = list.get(0);—— 因为具体上界不确定,无法保证返回值是更具体的类型
纯通用操作用 ?(无界通配符)
当方法完全不关心元素类型,只调用 Object 层方法(如 toString()、equals()、size())时,它最简洁。
- 声明形如
List>,可接收任意List<x></x>(X 为任意引用类型) - 遍历时只能用
Object接收元素,例如:for (Object item : list) - 不能调用
add()—— 连Object都不能加,因为编译器无法确保不破坏内部一致性(比如向本是List<string></string>的List>中加Integer就会出错)
记住 PECS 原则,别记混
Producer Extends,Consumer Super —— 这是判断用哪个通配符的口诀:
- 你要从集合“产出”(读取)T 类型数据 → 用
? extends T - 你要向集合“消费”(写入)T 类型数据 → 用
? super T - 既不产也不消,只做容器级操作 → 用
?
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











