java中泛型通配符的核心目的是实现安全的类型兼容:无界?用于灵活接收任意泛型类型但仅支持object级读取;

Java 中使用泛型通配符(?)的核心目的,是让方法或变量能接收多种具体泛型类型的实例,而无需为每种类型单独重载方法。它不改变泛型的本质,而是绕过编译器对“精确类型匹配”的强制要求,实现安全的、受限的类型兼容。
无界通配符 ?:最基础的灵活接收
写成 List> 或 Collection>,表示“某个确定但未知的具体类型”。它允许你传入 List<string></string>、List<integer></integer>、Set<date></date> 等任意参数化类型,只要该类型本身合法。
- ✅ 可以安全调用不依赖泛型参数的方法,比如
size()、isEmpty()、iterator() - ✅ 可以遍历并读取元素——但必须用
Object接收,因为编译器只知道它是“某种类型”,不确定具体是什么 - ❌ 不能向集合中添加任何元素(
null除外),因为编译器无法验证你加的值是否符合那个未知类型
上界通配符 ? extends T:适合“只读”场景
例如 List extends Number>,表示“某个 Number 的子类型(如 Integer、Double)的列表”。它把通配符限制在了继承链的上半部分。
- ✅ 可以安全读取元素,并直接赋给
Number类型变量(因为所有子类都可向上转型) - ❌ 依然不能添加任何非
null的元素——哪怕你传的是List<integer></integer>,编译器也不知道这个?具体是不是Integer,所以禁止写入 - 典型用途:处理一组具有共同父类的数据,比如统一打印所有数字型集合的值
下界通配符 ? super T:适合“只写”或“消费”场景
例如 List super Integer>,表示“某个 Integer 的父类型(如 Number 或 Object)的列表”。它放宽了写入的兼容性。
- ✅ 可以安全地向其中添加
Integer实例(因为Integer能放进任何其父类的容器) - ❌ 读取时只能用
Object接收——因为你不知道它实际是List<number></number>还是List<object></object>,没有更具体的上界保证 - 典型用途:设计通用收集器,比如一个方法把一堆
Integer统一塞进一个更宽泛的集合
为什么不能混用读写?记住 PECS 原则
这是理解通配符行为的关键口诀:Producer-Extends,Consumer-Super。
- 如果你要从集合中取数据(Producer),用
? extends T - 如果你要往集合中放数据(Consumer),用
? super T - 如果既读又写,通常就别用通配符,直接用具体泛型类型更清晰安全
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











