Java泛型通配符用于提升操作ArrayList的方法的通用性与类型安全性:ArrayList<?>适用于只读场景;? extends T支持安全读取子类型;? super T支持安全写入子类型;通配符主要应用于方法参数而非变量声明。

Java 泛型通配符与 ArrayList 配合使用,核心在于让方法能安全地处理多种具体类型的 ArrayList,同时保持编译期类型检查。关键不是“让 ArrayList 变得更灵活”,而是“让操作 ArrayList 的方法更通用且类型安全”。
通配符 ?:接收任意类型 ArrayList 的基础写法
当方法只读取 ArrayList 内容、不修改时,用 ArrayList<?> 最合适:
- 声明形参为
ArrayList<?>,表示该参数可接收ArrayList<String>、ArrayList<Integer>、ArrayList<Student>等任意具体泛型的 ArrayList 实例; - 内部只能用
Object接收元素(如list.get(0)返回Object),不能调用子类特有方法,也不能添加非null元素; - 适合打印、统计长度、判断是否为空等通用只读操作。
? extends T:安全读取子类型集合(上界通配符)
当你需要从 ArrayList 中读出统一的父类型数据(比如所有数字都当 Number 处理),就用 ArrayList<? extends Number>:
- 可以传入
ArrayList<Integer>、ArrayList<Double>、ArrayList<BigDecimal>等; - 方法内可安全调用
get()并赋值给Number或其父类(如Object); - 但不能调用
add()添加任何具体数值(连new Integer(5)都不行),因为编译器无法确认实际类型——只允许add(null)。
? super T:安全写入子类型对象(下界通配符)
当你需要往 ArrayList 中批量添加某类对象(比如统一加 Integer),但又希望它能兼容更宽泛的容器类型,就用 ArrayList<? super Integer>:
立即学习“Java免费学习笔记(深入)”;
- 可接收
ArrayList<Integer>、ArrayList<Number>、ArrayList<Object>; - 可以安全调用
add(new Integer(42))、add(100)(自动装箱),因为所有目标类型都支持 Integer 及其子类; - 但读取时只能用
Object接收(如list.get(0)是Object),不能直接转成Integer或Number,除非你额外做 instanceof 判断。
实际搭配建议
别在字段或变量声明里滥用通配符——它主要为**方法参数设计**:
- 定义工具方法时优先考虑通配符,例如:
public static void printAll(ArrayList<?> list); - 避免写
ArrayList<?> list = new ArrayList<>();—— 这样创建不了实例,编译报错; - 日常声明 ArrayList 变量仍用具体类型,如
ArrayList<String> names = new ArrayList<>();; - 需要泛型复用逻辑时,也可考虑泛型方法,比通配符更灵活(如
<T> void copy(List<T> src, List<T> dest))。


















