通配符不能嵌套,但可在泛型嵌套结构的任意层类型参数处单独使用,如List<Map<String, ?>>,仅用于声明、形参或返回值,不可用于实例化。

Java 泛型通配符在多层嵌套中不是“嵌套使用”,而是**在嵌套结构的某一层类型参数上单独应用**。理解的关键在于:通配符作用的是「泛型类型参数的位置」,而不是「嵌套层数」本身。
通配符不能嵌套,但可出现在任意嵌套层级的类型参数处
比如 List<Map<String, ?>> 是合法的,其中 ? 出现在 Map 的 value 类型位置;而 List<?> 中的 ? 则作用于 List 的元素类型。两者没有“? 套 ?”的关系,只是分别在不同层级的泛型参数上用了通配符。
- List<Map<String, ?>>:外层 List 元素是 Map<String, V>,V 未知(可以是 String、LocalDateTime、User 等)
- Map<String, List<? extends Number>>:value 是 List,该 List 只能装 Number 或其子类(Integer、Double),但具体哪一种不指定
- List<List<? super Integer>>:外层 List 的每个元素是 List<U>,U 必须是 Integer 或其父类(如 Number、Object)
为什么不能写 new ArrayList<?>()?
因为通配符仅用于**类型声明、形参或返回值**,不是真实类型,JVM 无法据此构造对象。它只是一种编译期约束占位符。
- ✅ 正确:List<?> list = new ArrayList<String>();
- ❌ 错误:List<?> list = new ArrayList<?>();(语法非法)
- ✅ 替代方案:用具体类型实例化,再用通配符引用,例如 List<? extends CharSequence> seqs = new ArrayList<String>();
各通配符在嵌套结构中的行为差异
嵌套不影响通配符的基本语义,但会放大其读写限制:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- ?(无界):只能调用 size()、get()(返回 Object)、isEmpty() 等不依赖具体类型的方法
- ? extends T:适合只读场景,get() 返回 T,add() 禁止(连 null 都不允许)
- ? super T:适合只写场景,add(T) 安全,get() 只能返回 Object
例如 Map<String, List<? extends Number>> data 中,你可以安全地遍历每个 List 并读出 Number,但不能往任一 List 里 add 新元素。
实际开发中怎么选?记住 PECS 原则
Producer Extends, Consumer Super —— 如果你从嵌套结构中取数据(如遍历 List<? extends X>),用 extends;如果你往里放数据(如向 List<? super X> 添加 X 实例),用 super。
- 打印所有数字:void printAll(List<? extends Number> nums)
- 收集整数到通用容器:void collectInts(List<? super Integer> target, List<Integer> source)

















