Java中上限通配符(? extends T)用于源集合保证可读性,目标集合用Collection<T>保证可写性,实现类型安全的通用拷贝:copyTo(Collection<? extends T> src, Collection<T> dest)调用dest.addAll(src)完成无转换拷贝。

Java 中利用上限通配符(? extends T)可以安全地从只读集合中读取元素,但不能向其中写入。要实现一个通用的集合元素拷贝工具方法,核心是:**源集合用 ? extends T 保证可读性,目标集合用 Collection<T> 保证可写性,且类型兼容**。
明确泛型约束与职责分离
拷贝操作本质是“读出 → 转换(可选)→ 写入”。上限通配符仅用于源端,确保能安全取出子类型实例;目标集合必须声明具体类型 T,才能接受这些实例。
- 源集合类型应为
Collection<? extends T>:允许传入ArrayList<String>、LinkedList<Object>等任何T或其子类型的集合 - 目标集合类型应为
Collection<T>:保证能接收所有从源中读出的T类型元素 - 不能把目标也写成
Collection<? super T>—— 虽然语法合法,但会失去编译期类型安全,且不符合“通用拷贝”的直观语义
基础拷贝方法(无转换)
最简场景:直接将源集合中所有元素添加到目标集合,要求元素类型兼容。
public static <T> void copyTo(Collection<? extends T> src, Collection<T> dest) {
if (src == null || dest == null) return;
dest.addAll(src); // addAll 接受 Collection<? extends T>,天然适配
}
调用示例:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
copyTo(Arrays.asList("a", "b"), new ArrayList<Object>());✅(String是Object子类) -
copyTo(Arrays.asList(1, 2), new ArrayList<Number>());✅(Integer是Number子类) -
copyTo(Arrays.asList(new Date()), new ArrayList<Long>());❌ 编译失败(Date不是Long子类)
带类型转换的拷贝(需显式映射)
若源元素类型与目标所需类型不直接兼容(如 String → Integer),需额外提供转换函数。此时上限通配符仍用于约束源,转换逻辑由用户控制:
public static <S, T> void copyAndConvert(
Collection<? extends S> src,
Collection<T> dest,
Function<S, T> converter) {
if (src == null || dest == null || converter == null) return;
for (S item : src) {
dest.add(converter.apply(item));
}
}
调用示例:
立即学习“Java免费学习笔记(深入)”;
copyAndConvert(Arrays.asList("1", "2"), list, Integer::parseInt);copyAndConvert(Arrays.asList("hello"), list, s -> s.length());
注意边界与常见陷阱
使用上限通配符时需警惕几个典型问题:
-
Collection<? extends Number>不能调用add(new Integer(1))—— 编译器不知道具体是Integer、Double还是其他子类,禁止写入是安全设计 - 不要试图在方法内新建泛型集合返回(如
new ArrayList<? extends T>())—— 通配符不能用于构造,应返回ArrayList<T>或使用限定通配符接收(如Collection<? extends T>作为返回类型) - 如果源集合为空或为
null,务必判空,避免NullPointerException


















