核心是用? extends t(只读,生产者)或? super t(只写,消费者)放宽类型约束并保障类型安全:前者允许安全读取为t但禁止写入,后者允许安全写入t但读取仅得object,遵循pecs原则。

Java 泛型中用通配符接收集合参数,核心是用 ? extends T 或 ? super T 来放宽类型约束,同时守住编译期安全底线。不是为了绕过类型检查,而是让方法能适配更合理的父类/子类集合,又不破坏类型一致性。
用 ? extends T 接收“只读”集合
当方法只需从集合里读取元素、且所有元素都能当作 T 处理时,用上界通配符:
- 声明形如 List extends Number>,可传入
List<integer></integer>、List<double></double>、List<number></number> - 能安全调用
get(i),返回值可自动赋给Number类型变量(如Number n = list.get(0);) - 但不能调用
add(...)—— 编译器无法确认你加的是否属于该未知子类型(比如往List extends Number>里加Float,而实际是List<integer></integer>就会出错)
用 ? super T 接收“可写”集合
当方法主要向集合中添加 T 类型实例,且希望支持更宽泛的目标类型时,用下界通配符:
- 声明形如 List super Integer>,可传入
List<integer></integer>、List<number></number>、List<object></object> - 能安全调用
add(new Integer(42))—— 因为Integer是所有这些类型的子类或本身 - 但读取时只能当作
Object(如Object o = list.get(0);),因为具体上界不确定
别直接用 ?,除非真不需要类型信息
List> 表示“某个确定但未知的类型”,它既不能安全读(只能当 Object),也不能安全写(连 Object 都不能加,因为可能破坏内部一致性)。它适合纯结构性操作,比如清空、判空、获取大小,或作为桥接过渡类型。日常业务方法中应尽量避免。
结合 PECS 原则快速判断
记住一句话:**Producer 使用 extends,Consumer 使用 super**。
- 如果集合是数据“生产者”(你从中取东西用),选 ? extends T
- 如果集合是数据“消费者”(你往里塞东西),选 ? super T
- 像
Collections.copy(dest, src)就是典型双通配符组合:copy(List super T> dest, List extends T> src)—— 目标可接收 T 及其父类,源可提供 T 及其子类,完美匹配复制语义
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











