了解Java中varargs的意外行为

了解Java中varargs的意外行为,java,Java,我在读答案,上面写着 还请注意,使用显式数组参数调用泛型vararg方法可能会产生与预期不同的行为: public <T> void foo(T... params) { ... } int[] arr = {1, 2, 3}; foo(arr); // passes an int[][] array containing a single int[] element Varargs仅适用于引用类型。自动装箱不适用于基元数组。以下工作: Integer[] myNumbers =

我在读答案,上面写着

还请注意,使用显式数组参数调用泛型vararg方法可能会产生与预期不同的行为:

public <T> void foo(T... params) { ... }
int[] arr = {1, 2, 3};
foo(arr); // passes an int[][] array containing a single int[] element
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);
  • 请注意,将
    intarr
    传递到
    tVarargs
    会导致创建单个二维数组
    [[I
    和单个元素。但是,此数组的类型是什么
  • 此外,将
    intarr
    传递到
    objVarargs()
    会创建包含单个数组元素的一维数组
    [Ljava.lang.Object
  • 对于rest,它创建了1-D数组,其中包含所传递的元素数——这是所需的行为

有人能更清楚地了解前两种行为吗?这两种行为是不同的行为还是相同的行为,我的意思是它们背后有不同或相同的原因。这些原因是什么?是否有其他情况导致不同的意外行为?

这两种行为是由同一问题导致的-泛型类型参数和d
Object
变量只能保存引用类型。原语(如
int
)不是引用类型,因此将
int
数组传递给varargs方法(不管它是
Object…A
还是
t…s
)结果该方法接受一个具有单个元素的数组,并且该单个元素是
int
数组

因此,您可以将其视为2维<代码> int <代码>数组(即<代码> int [][]/COD>),包含一行。

请注意,
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)
中是
T[]
(当
T
int[]
时,数组的类型是
int[]


顺便说一句,
[[I
是一个二维
int
数组的类名(即
int[][]
)。

我不知道这里有什么让你困惑。
Type…
只是
Type[]
但允许我们将
类型的参数作为列表传递,而不是手动将其包装到数组中。
仅限于引用类型(它不能表示像
int
这样的基元类型),这意味着
t...
as
t[]
不能是
int[]
。如果传递
int[]
array然后
T
可以使用的最具体的对象类型是数组本身。所以既然
T
现在是
int[]
T…。
就像
int[]…
一样,它导致
int[]
(这就是
[[I
所代表的)。
对象…
就是
对象[]
array,这就是您在其他方法中看到的
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,
[Ljava.lang.Integer;
3
1,2,3,