核心是安全适配更广类型范围:只读用<? extends T>(如List<? extends Number>可读Integer/Double但不可add),只写用<? super T>(如List<? super Integer>可add Integer但读取仅得Object),纯通用用<?>;遵循PECS原则——Producer Extends、Consumer Super。

Java 中用泛型通配符控制方法参数的类型兼容性,核心不是“绕过检查”,而是让方法能安全适配更广的泛型类型范围。关键在明确读写意图:只读用 ? extends T,只写用 ? super T,纯通用操作才用 ?。
用 ? extends T 接收只读集合
当方法只需从集合中读取元素,并把它们当作 T 类型来处理时,上界通配符最合适。
- 声明形如 List<? extends Number>,可接收 List<Integer>、List<Double> 或 List<Number>
- 能安全调用 get(i),返回值可直接赋给 Number 变量(例如 Number n = list.get(0);)
- 不能调用 add() —— 编译器无法确认你加的对象是否属于该未知子类型(比如往 List<? extends Number> 里加 Float,而实际是 List<Integer> 就会破坏类型安全)
用 ? super T 接收可写集合
当方法主要向集合中添加 T 类型的实例,且希望目标集合类型可以更宽泛(比如接受父类容器)时,下界通配符是唯一选择。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 声明形如 List<? super Integer>,可接收 List<Integer>、List<Number> 或 List<Object>
- 能安全调用 add(new Integer(42)) —— 因为 Integer 是所有这些类型的子类或本身
- 读取时只能按 Object 处理(例如 Object o = list.get(0);),因为具体上界不确定,无法保证返回值是更具体的类型
用 ? 处理完全类型无关的操作
当方法不依赖元素具体类型,只调用 Object 层的方法(如 toString()、equals()、hashCode()),无界通配符最简洁。
立即学习“Java免费学习笔记(深入)”;
- 声明形如 List<?>,可接收任意 List<X>(X 为任意具体类型)
- 遍历时只能用 Object 接收元素(例如 for (Object item : list))
- 不能调用 add() —— 连 Object 都不能加,因为编译器无法确保不破坏内部一致性(比如向 List<String> 传入的 List<?> 中加一个 Integer 就会出错)
牢记 PECS 原则,避免混淆
这是理解三者分工的口诀:
- Producer – Extends:产出数据(读取)→ 用 ? extends T
- Consumer – Super:消费数据(写入)→ 用 ? super T
- 像 Collections.copy(dest, src) 这样的标准方法就是典型体现:src 是生产者(? extends T),dest 是消费者(? super T)

















