我正在尝试编写一个带有一些字符串并对它们做某事的函数。
我要做的唯一事情是字符串集循环遍历它们。现在我最终得到了一个尴尬的构造
public void foo(String[] myStrings){
foo(java.util.Arrays.asList(myStrings));
}
public void foo(Iterable<String> myStrings){
for(String i : myStrings){
bar(i);
}
}
因为
而感到多余for(String i : myStrings){
bar(i);
}
对于String []类型的myStrings来说是完全有效的代码。
是否有一个我可以接受foo的类,它将允许集合和数组?
答案 0 :(得分:9)
请参阅Why is an array not assignable to Iterable?
简答:不。根据我的理解,数组类型是合成代码,因此不实现Iterable
或任何其他类型。您需要提供重载方法或要求客户在呼叫站点呼叫Arrays.asList
。
答案 1 :(得分:3)
不幸的是,尽管for-each循环同时工作,但数组并没有实现Iterable
。
您可以专门接受Iterable
,因为传递数组有点旧学校(数组超过ArrayList
的性能优势可以忽略不计)。现有数组可以轻松打包并使用Arrays.asList(T... a)
转换为List
。
答案 2 :(得分:2)
尽管可以在for-each循环中使用数组,但它们不会实现Iterable
。只有两种可能性,要么就像您所说的那样重载方法,要么只提供可迭代变体并强制客户调用Arrays.asList()
。
如果您还想提供数组重载,可以将其签名从简单数组更改为varargs:
public void foo(String... myStrings){
foo(java.util.Arrays.asList(myStrings));
}
在这种情况下,请注意原始数组和原始包装数组之间的不兼容性:
static void foo(int... ints) {}
foo(new Integer[] {1, 2}); // compile error
和
static void foo(Integer... integers) {}
foo(new int[] { 1, 2 }); // compile error
最不起眼的部分,使用通用的varargs:
static <T> T[] foo(T... ts) {
return ts;
}
如果传递整数数组:
Integer[] integers = { 1, 2 };
System.out.println(Arrays.deepToString(foo(integers)));
> [1, 2]
ts
的值是一个包含2个元素的整数数组:1
和2
。
但是,如果你传递一个原始int数组,就会发生一件有趣的事情:
int[] ints = { 1, 2 };
System.out.println(Arrays.deepToString(foo(ints)));
> [[1, 2]]
在这种情况下,ts的值是一个int数组(int[][]
)的数组,只有一个元素,它是最初传递的数组。这样做的原因是int
不是Object
(自动装箱在这里没有帮助),而是一个整数数组,因此{{1}的值} type参数变为T
。