请注意以下代码行:
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[]
的实例,那还有什么实例?
答案 0 :(得分:24)
foo(1,2,3);
这一个自动装箱1
,2
和3
到Integer
(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... args
是Object[] 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
适用Varargs和Autoboxing的规则。编译器生成Object
数组,因为Object...
表示Object[]
。因此bar
不是Integer[]
的实例。这只是语法糖。