List<?> 和 Collection<?> 是类型擦除后的只读通用集合视图,用于安全接收任意具体泛型集合,支持 size()、isEmpty()、iterator() 等结构操作,但禁止添加元素(null 除外),遍历时元素视为 Object,适用于打印、统计、判空等不依赖具体类型的操作。

直接用 List<?> 或 Collection<?> 接收任意具体泛型集合,是解决“类型不兼容却需通用处理”的最轻量方式——它不关心元素是什么类型,只做安全的只读操作。
> 的核心定位:只读容器,类型擦除后的统一视图
Java 泛型不是协变的。哪怕 String 是 Object 的子类,List<String> 和 List<Object> 也互不兼容。> 就是为绕过这种刚性限制而生:它代表“某个确定但不可知的具体类型”,让方法能同时接受 List<Integer>、Set<Boolean>、ArrayList<String> 等所有参数化集合。
- 能调用所有继承自
Object的方法,比如size()、isEmpty()、toString()、iterator() - 遍历时只能把元素当作
Object处理,例如:for (Object o : list) { ... } - 不能调用任何子类特有方法(如
o.length()或o.intValue()),除非手动强转(不推荐) - 禁止向其中添加任何元素(
add()、addAll()全部编译报错),唯一例外是null
典型使用场景:打印、统计、判空、转换为数组
这些操作不依赖元素具体类型,只需集合结构本身。
- 打印全部元素:
public static void printAll(Collection<?> c) { c.forEach(System.out::println); } - 获取元素数量:
public static int count(Collection<?> c) { return c.size(); } - 转成 Object 数组:
Object[] arr = collection.toArray();(toArray(T[])不可用) - 判断是否含某对象(基于 equals):
c.contains("test")合法,因为contains参数是Object
和 extends T>、 super T> 的关键区别
> 是“完全未知”,而带边界的通配符是有方向的:
-
List<?>:既不能安全读成T,也不能安全写入T;适合纯结构操作 -
List<? extends Number>:可安全读作Number,但不能写(“生产者”角色) -
List<? super String>:可安全写入String,但读出来只能当Object(“消费者”角色)
常见误区提醒
别把它当成万能占位符来“绕过编译检查”:
- 错误写法:
List<?> list = new ArrayList<String>(); list.add("hello");→ 编译失败 - 错误理解:
Collection<?>不是Collection<Object>的父类,二者无继承关系 - 不能用于泛型类或方法声明:
class Box<?>或<?> void method()是非法语法 - 多个>彼此独立:
void copy(List<?> src, List<?> dest)中两个 ? 无关联,不能保证类型一致

















