我正在阅读this的答案,上面写着
还请注意,使用显式数组参数调用通用vararg方法可能会静默地产生与预期不同的行为:
public <T> void foo(T... params) { ... } int[] arr = {1, 2, 3}; foo(arr); // passes an int[][] array containing a single int[] element
this答案3中解释了类似的行为:
int[] myNumbers = { 1, 2, 3 }; System.out.println(ezFormat(myNumbers)); // prints "[ [I@13c5982 ]"
Varargs仅适用于引用类型。自动装箱不适用于图元数组。以下作品:
Integer[] myNumbers = { 1, 2, 3 }; System.out.println(ezFormat(myNumbers)); // prints "[ 1 ][ 2 ][ 3 ]"
我尝试了更简单的示例:
private static <T> void tVarargs(T ... s)
{
System.out.println("\n\ntVarargs ==========");
System.out.println(s.getClass().getName());
System.out.println(s.length);
for(T i : s)
System.out.print(s + ",");
}
private static void objVarargs(Object ... a)
{
System.out.println("\n\nobjVarargs =========== ");
System.out.println(a.getClass().getName());
System.out.println(a.length);
for(Object i : a)
System.out.print(i + ",");
}
int[] intarr = {1,2,3};
Integer[] Intarr = {1,2,3};
objVarargs(intarr);
objVarargs(Intarr);
tVarargs(intarr);
tVarargs(Intarr);
此打印
objVarargs ===========
[Ljava.lang.Object;
1
[I@7852e922,
objVarargs ===========
[Ljava.lang.Integer;
3
1,2,3,
tVarargs ==========
[[I
1
[[I@4e25154f,
tVarargs ==========
[Ljava.lang.Integer;
3
[Ljava.lang.Integer;@70dea4e,[Ljava.lang.Integer;@70dea4e,[Ljava.lang.Integer;@70dea4e,
intarr
传递到tVarargs
的通知会导致创建单个 2维数组 [[I
,其中包含单个元素。但是,此数组的类型是什么? intarr
传递到objVarargs()
会导致创建包含单个数组元素的 1-D数组 [Ljava.lang.Object
。 有人可以对前两种行为有更多的了解吗?这是两种不同的行为还是相同的行为,我的意思是背后有不同或相同的原因。这些原因到底是什么?还有其他情况导致不同的意外行为吗?
答案 0 :(得分:5)
这两个行为是由同一问题引起的-泛型类型参数和Object
变量都只能容纳引用类型。基元(例如int
)不是引用类型,因此将int
数组传递给varargs方法(无论是Object ... a
还是T ... s
)将导致该方法接受具有单个元素的数组,并且该单个元素是int
数组。
因此,您可以将其视为包含单个行的二维int
数组(即int[][]
)。
请注意,您在tVarargs(T ... s)
中有一个错字,导致输出混乱。应该是System.out.print(i + ",");
,而不是System.out.print(s + ",");
解决此问题后,两种方法都会为Integer[]
输入产生相同的输出:
[Ljava.lang.Integer;
3
1,2,3,
int[]
输入的输出差异是由于在objVarargs(Object ... a)
中varargs数组的类型为Object[]
,而在tVarargs(T ... s)
中为{ {1}}(并且当T[]
是T
时,数组的类型是int[]
)。
顺便说一句,int[][]
是二维[[I
数组(即int
)的类名。