在下面的代码中,x.test()
会返回[1,2]
。
所以y = [1,2]
。
然而f([1,2])
打印1
,但f(y)
打印2
。
如何撰写f(y)
以便打印1
?
不正常,f(z)
打印1
,即使是z = y
。
def f = { Object... args -> println args.size(); };
class Test { Object[] test() { return [1,2]; } }
def x = new Test();
def y = x.test();
def z = [1,2];
f([1,2]); // 1
f(y); // 2
f(z); // 1
答案 0 :(得分:11)
问题是y
和z
虽然看起来是相同的,但实际上是不同类型的。 y
是Object[]
而z
是ArrayList<Integer>
。 Groovy以不同的方式处理数组和列表,自动将前者强制转换为varargs参数列表,而不是后者。
println y.getClass(); // class [Ljava.lang.Object
println z.getClass(); // class java.util.ArrayList
至于问题的解决方案,请更改test()
以返回List
而不是数组:
class Test { List test() { return [1,2]; } }
当您将数组传递给f
时,或手动将数组强制转换为列表:
f(y as List); // 1
答案 1 :(得分:2)
Groovy中的表达式[1,2]
表示包含两个成员Integer.valueOf(1)
和Integer.valueOf(2)
的ArrayList。因此,当您调用f([1,2])
时,Groovy会创建一个包含此ArrayList作为其唯一项的单元素数组,并将该数组作为闭包参数传递。
但声明x.test()
返回Object[]
,因此[1,2]
ArrayList将被Object[]
转换为两个元素return
。因此y
已经是Object[]
,并且不需要在varargs数组中装箱以传递给f
。
您需要将y
更改回列表,方法是更改test()
的返回类型或说
f(y as List)
相反,您可以使用 spread 运算符
f(*z) // 2
将提取ArrayList的元素并将它们作为调用的单独参数传递(然后将照常将其打包到varargs数组中)。
答案 2 :(得分:0)
y
是[Ljava.lang.Object
的一个实例,而[1,2]
和z
的实例是ArrayList
数组将size() == 2
和ArrayList
计数作为一个参数,但它们包含两个元素
Groovy会为你做一些类型转换;)