为什么 foo(1,2,3) 没有作为 Integer[] 传递给可变参数方法 foo(Object...)
Why is foo(1,2,3) not passed to varargs method foo(Object... ) as an Integer[]
请注意以下代码行:
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[]
的实例,那么它是什么的实例?
bar 不是整数数组的情况是因为它是您在 foo
方法签名中指定的对象数组:Object... args
是 Object[] args
的语法糖当解析到这个方法时,编译器将创建一个对象数组。
为了始终拥有一个整数数组,您可以将 foo
方法签名更改为 foo(Integer... args)
foo(1,2,3);
这个自动装箱 1
、2
和 3
到 Integer
(s),因为它们是 Object
子类型,Object[]
数组被创建,由三个 Integer
组成。数组 Object[]
不是 Integer[]
,这就是为什么你得到 false
.
foo(new Integer(1), new Integer(2), new Integer(3));
在这里,没有应用自动装箱,但最后您将再次拥有一个由三个 Integer
组成的数组 Object[]
。同样,Object[]
不是 Integer[]
,这就是你得到 false
.
的原因
foo(new Integer[]{1,2,3});
这里你有只有一个参数,不像前两种情况,你有三个包裹在一个数组中。因此,只有一个参数 Integer[]
,在运行时比较 bar instanceof Integer[]
将 return true
,因为整数是您实际拥有的。
foo(new Integer[] {new Integer(1), new Integer(2), new Integer(3)});
与上一个相同 - 在运行时,您将检查提供的数组 Integer[]
是否为 Integer
的数组,即 true
.
在调用 foo(1,2,3);
的情况下,编译器(在本例中为 javac
)生成代码 foo(new Object[]{new Integer(1), new Integer(2), new Integer(3)})
。
javac
应用 Varargs and Autoboxing 的规则。编译器生成一个 Object
的数组,因为 Object...
表示 Object[]
。因此 bar
不是 Integer[]
的实例。它只是语法糖。
根据 Java Language Specification:
the result of the instanceof operator is true if the value of the RelationalExpression is not null and the reference could be cast (§15.16) to the ReferenceType without raising a ClassCastException.
在您的情况下,Object[]
参数无法转换为 Integer[]
,因此它 returns 为 false。
Varargs 只是用于创建和传递数组的语法糖。由于您将方法定义为
public static void foo(Object... bar)
如果您将方法调用为 foo(1,2,3)
或 foo(new Integer(1), new Integer(2), new Integer(3))
,Java 会为您创建一个 Object[]
数组。
但是,您也可以将自己的数组传递给需要可变参数的方法。在这种情况下 Java 不会为您创建新数组,它只是传递您创建的数组。在最后两次调用中,您显式创建了一个 Integer[]
数组。
请注意以下代码行:
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[]
的实例,那么它是什么的实例?
bar 不是整数数组的情况是因为它是您在 foo
方法签名中指定的对象数组:Object... args
是 Object[] args
的语法糖当解析到这个方法时,编译器将创建一个对象数组。
为了始终拥有一个整数数组,您可以将 foo
方法签名更改为 foo(Integer... args)
foo(1,2,3);
这个自动装箱 1
、2
和 3
到 Integer
(s),因为它们是 Object
子类型,Object[]
数组被创建,由三个 Integer
组成。数组 Object[]
不是 Integer[]
,这就是为什么你得到 false
.
foo(new Integer(1), new Integer(2), new Integer(3));
在这里,没有应用自动装箱,但最后您将再次拥有一个由三个 Integer
组成的数组 Object[]
。同样,Object[]
不是 Integer[]
,这就是你得到 false
.
foo(new Integer[]{1,2,3});
这里你有只有一个参数,不像前两种情况,你有三个包裹在一个数组中。因此,只有一个参数 Integer[]
,在运行时比较 bar instanceof Integer[]
将 return true
,因为整数是您实际拥有的。
foo(new Integer[] {new Integer(1), new Integer(2), new Integer(3)});
与上一个相同 - 在运行时,您将检查提供的数组 Integer[]
是否为 Integer
的数组,即 true
.
在调用 foo(1,2,3);
的情况下,编译器(在本例中为 javac
)生成代码 foo(new Object[]{new Integer(1), new Integer(2), new Integer(3)})
。
javac
应用 Varargs and Autoboxing 的规则。编译器生成一个 Object
的数组,因为 Object...
表示 Object[]
。因此 bar
不是 Integer[]
的实例。它只是语法糖。
根据 Java Language Specification:
the result of the instanceof operator is true if the value of the RelationalExpression is not null and the reference could be cast (§15.16) to the ReferenceType without raising a ClassCastException.
在您的情况下,Object[]
参数无法转换为 Integer[]
,因此它 returns 为 false。
Varargs 只是用于创建和传递数组的语法糖。由于您将方法定义为
public static void foo(Object... bar)
如果您将方法调用为 foo(1,2,3)
或 foo(new Integer(1), new Integer(2), new Integer(3))
,Java 会为您创建一个 Object[]
数组。
但是,您也可以将自己的数组传递给需要可变参数的方法。在这种情况下 Java 不会为您创建新数组,它只是传递您创建的数组。在最后两次调用中,您显式创建了一个 Integer[]
数组。