简体   繁体   English

了解Java中varargs的意外行为

[英]Understanding unexpected behaviors of varargs in Java

I was reading this answer, where it says 我正在读这个答案,它说的是

Note also that calling a generic vararg method with an explicit array parameter may silently produce different behaviour than expected: 另请注意,使用显式数组参数调用泛型vararg方法可能会默默地产生与预期不同的行为:

 public <T> void foo(T... params) { ... } int[] arr = {1, 2, 3}; foo(arr); // passes an int[][] array containing a single int[] element 

Similar behavior is exaplained in this answer gotcha 3: 类似的行为在这个答案得到解释3:

 int[] myNumbers = { 1, 2, 3 }; System.out.println(ezFormat(myNumbers)); // prints "[ [I@13c5982 ]" 

Varargs only works with reference types. Varargs仅适用于引用类型。 Autoboxing does not apply to array of primitives. 自动装箱不适用于基元数组。 The following works: 以下作品:

 Integer[] myNumbers = { 1, 2, 3 }; System.out.println(ezFormat(myNumbers)); // prints "[ 1 ][ 2 ][ 3 ]" 

I tried simpler examples: 我尝试了更简单的例子:

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);

This prints 这打印

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,
  • Notice passing intarr to tVarargs results in creation of single 2 dimensional array [[I wit single element . 注意将intarr传递给tVarargs导致创建单个二维数组 [[I wit wit single element However, what is the types of this array? 但是,这个数组的类型是什么?
  • Also, passing intarr to objVarargs() results in creation of 1-D array [Ljava.lang.Object containing single array element . 此外,将intarr传递给objVarargs()导致创建包含单个数组元素1-D数组 [Ljava.lang.Object
  • For rest, it creates 1-D array with as many elements as passed - the desired behavior. 休息时,它创建的1-D数组包含与传递的元素一样多的元素 - 所需的行为。

Can someone shed more light on first two behaviors? 有人能否对前两种行为有更多的了解? Are these two different behaviors or same behaviors, I mean having different or same reason behind them. 这两种不同的行为或相同的行为,我的意思是背后有不同或相同的原因。 What are those reasons, in depth? 这些原因究竟是什么? Is there any other cases resulting in different unexpected behavior? 是否有其他案例导致不同的意外行为?

These two behaviors result from the same issue - both generic type parameters and Object variables can only hold reference types. 这两个行为来自同一个问题 - 泛型类型参数和Object变量只能保存引用类型。 A primitive (such as int ) is not a reference type, so passing an int array to a varargs method (and it doesn't matter if it's Object ... a or T ... s ) results in the method accepting an array having a single element, and that single element is the int array. 基元(例如int )不是引用类型,因此将int数组传递给varargs方法(如果它的Object ... aT ... s无关紧要)会导致接受数组的方法具有单个元素,并且该单个元素是int数组。

Therefore you can consider it as a 2 dimensional int array (ie int[][] ) containing a single row. 因此,您可以将其视为包含单行的2维int数组(即int[][] )。

Note that you have a typo in tVarargs(T ... s) which results in confusing output. 请注意, tVarargs(T ... s)存在拼写错误,导致输出混乱。 It should be System.out.print(i + ","); 它应该是System.out.print(i + ","); , not System.out.print(s + ","); ,而不是System.out.print(s + ",");

Once you fix that, both methods produce the same output for the Integer[] input: 修复后,两个方法都会为Integer[]输入生成相同的输出:

[Ljava.lang.Integer;
3
1,2,3,

The difference in the outputs for the int[] input results from the fact that in objVarargs(Object ... a) , the type of the varargs array is Object[] , and in tVarargs(T ... s) it's T[] (and when T is an int[] , the type of the array is an int[][] ). int[]输入的输出差异是由于在objVarargs(Object ... a) ,varargs数组的类型是Object[] ,而在tVarargs(T ... s)它是T[] (当Tint[] ,数组的类型是int[][] )。

BTW, [[I is the class name of a two dimensional int array (ie int[][] ). BTW, [[I是二维int数组的类名(即int[][] )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM