guava的iterables.concat不支持直接传入iterable

Guava 的 Iterables.concat 本身不直接支持上界通配符(? extends T)用于“平铺多个不同子类型集合”,但你可以通过类型擦除规则和合理的泛型边界设计,安全地将多个 Iterable extends T> 拼接成一个 Iterable<t></t>。关键在于:**不要试图把 Iterables.concat 的参数声明为 Iterable extends T> 数组或列表,而是让每个参数独立推断为 Iterable<x></x>,其中 X 是 T 的子类型——Java 泛型会自动向上转型为 Iterable<t></t>**。
为什么不能直接传 Iterable extends T>[]?
Iterables.concat 是可变参数方法:public static <t> Iterable<t> concat(Iterable<t>... inputs)</t></t></t>。它的形参是 Iterable<t>...</t>,不是 Iterable extends T>...。如果你强行传入 Iterable<string></string> 和 Iterable<integer></integer> 给同一个 T,编译器无法统一 T 类型(因为 String 和 Integer 没有共同非 Object 的父类)。但如果你传的都是 Iterable extends Number>,比如 Iterable<integer></integer> 和 Iterable<double></double>,就可以统一为 T = Number:
-
Iterable<integer></integer>是Iterable extends Number>的具体实例,能赋值给Iterable<number></number>(协变) - 所以
Iterables.concat(ints, doubles)可以成功推断T = Number,返回Iterable<number></number>
正确写法:显式指定类型参数 + 用具体子类型集合
不依赖通配符变量,而是直接传入具体类型的 Iterable,让类型推断自然工作:
List<integer> ints = Arrays.asList(1, 2);
List<double> doubles = Arrays.asList(3.14, 2.71);
// ✅ 正确:编译器推断 T = Number
Iterable<number> combined = Iterables.concat(ints, doubles);
for (Number n : combined) {
System.out.println(n); // 输出 1, 2, 3.14, 2.71
}</number></double></integer>
注意:ints 和 doubles 本身不是 Iterable extends Number> 类型变量,而是具体类型;但它们在调用时被视作 Iterable<number></number> 的兼容实参。
如果必须用通配符容器(如 List>),需手动 cast 或辅助方法
Java 不允许将 List<iterable extends number>></iterable> 直接转为 Iterable<number>...</number>。此时需借助工具方法绕过泛型限制(不推荐,但可行):
- 方案一:用
FluentIterable+append链式调用(更安全) - 方案二:写一个泛型桥接方法,利用类型擦除做 unchecked cast(需加
@SuppressWarnings("unchecked"))
例如:
public static <t> Iterable<t> concatExtends(List<iterable extends t>> sources) {
@SuppressWarnings("unchecked")
Iterable<t>[] array = sources.toArray(new Iterable[0]);
return Iterables.concat(array);
}</t></iterable></t></t>
调用:concatExtends(Arrays.asList(ints, doubles)) → 返回 Iterable<number></number>。本质是信任调用方传入的确实是 ? extends T,避免运行时 ClassCastException。
常见错误与规避
❌ 错误写法:Iterable extends Number> a = ints; Iterable extends Number> b = doubles; Iterables.concat(a, b);
原因:此时 a 和 b 类型都是 Iterable extends Number>,但通配符是独立的,编译器无法统一为同一 T,推断失败。
✅ 正确思路:让参数保持具体类型,或统一提升到共同上界再传入。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











