为什么foo(1,2,3)没有作为整数[]传递给varargs方法foo(Object ...)

时间:2015-12-03 08:31:24

标签: java variadic-functions autoboxing

请注意以下代码行:

public static void main(String[] args)  {
    foo(1,2,3);
    System.out.println("-------------------------------------");
    foo(new Integer(1), new Integer(2), new Integer(3));
    System.out.println("-------------------------------------");
    foo(new Integer[]{1,2,3});
    System.out.println("-------------------------------------");
    foo(new Integer[] {new Integer(1), new Integer(2), new Integer(3)});
}

public static void foo(Object... bar) {
    System.out.println("bar instanceof Integer[]:\t" + (bar instanceof Integer[]));
    System.out.println("bar[0] instanceof Integer:\t" + (bar[0] instanceof Integer));
    System.out.println("bar.getClass().isArray():\t" + bar.getClass().isArray());
}

此代码段的输出为:

bar instanceof Integer[]:   false
bar[0] instanceof Integer:  true
bar.getClass().isArray():   true
-------------------------------------
bar instanceof Integer[]:   false
bar[0] instanceof Integer:  true
bar.getClass().isArray():   true
-------------------------------------
bar instanceof Integer[]:   true
bar[0] instanceof Integer:  true
bar.getClass().isArray():   true
-------------------------------------
bar instanceof Integer[]:   true
bar[0] instanceof Integer:  true
bar.getClass().isArray():   true

这让我很困惑!我不明白为什么foo(1,2,3) bar instanceof Integer[]这个词是假的。

如果在这些情况下bar不是Integer[]的实例,那还有什么实例?

5 个答案:

答案 0 :(得分:24)

  • foo(1,2,3);

这一个自动装箱123Integer(s),因为它们是Object子类型,{{1}创建了一个数组,由三个Object[]组成。数组Integer不是Object[],这就是您获得Integer[]的原因。

  • false

此处不会应用自动装箱,但最终您将再次拥有一个由foo(new Integer(1), new Integer(2), new Integer(3));组成的数组Object[]。同样,Integer不是Object[],这就是您获得Integer[]的原因。

  • false

这里有只有一个参数,与之前的两种情况不同,在这两种情况下,你有三个包装在一个数组中。因此,只有一个参数foo(new Integer[]{1,2,3});,在运行时,比较Integer[]将返回bar instanceof Integer[],因为整数是您实际拥有的。

  • true

与上一个相同 - 在运行时,您将检查提供的数组foo(new Integer[] {new Integer(1), new Integer(2), new Integer(3)});是否是Integer[]的数组,Integer

答案 1 :(得分:5)

根据error 21212

  

如果RelationalExpression的值不为null并且引用可以在不引发ClassCastException的情况下将引用(第15.16节)转换为ReferenceType,则instanceof运算符的结果为true。

在您的情况下,Object[]参数无法转换为Integer[],因此返回false。

答案 2 :(得分:3)

bar不是整数数组的情况是因为它是您在foo方法签名中指定的Object数组:Object... argsObject[] args的语法糖,当解析为此方法,编译器将创建一个Object数组。

为了始终拥有一个Integer数组,您可以将foo方法签名更改为foo(Integer... args)

答案 3 :(得分:3)

Varargs只是用于创建和传递数组的语法糖。由于您将方法定义为

public static void foo(Object... bar) 

如果您将方法称为Object[]foo(1,2,3),则Java会为您创建foo(new Integer(1), new Integer(2), new Integer(3))数组。

但是,您也可以将自己的数组传递给需要varargs参数的方法。在这种情况下,Java不会为您创建新数组,它只是传递您创建的数组。在最后两次调用中,您明确创建了一个Integer[]数组。

答案 4 :(得分:2)

在调用foo(1,2,3);的情况下,编译器(在本例中为javac)生成代码foo(new Object[]{new Integer(1), new Integer(2), new Integer(3)})

javac适用VarargsAutoboxing的规则。编译器生成Object数组,因为Object...表示Object[]。因此bar不是Integer[]的实例。这只是语法糖。