了解Java中varargs的意外行为

时间:2018-11-13 13:07:22

标签: java

我正在阅读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
  • 对于其余部分,它会创建一维数组,其中包含传递的元素数量-所需的行为。

有人可以对前两种行为有更多的了解吗?这是两种不同的行为还是相同的行为,我的意思是背后有不同或相同的原因。这些原因到底是什么?还有其他情况导致不同的意外行为吗?

1 个答案:

答案 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)的类名。