假设我有这样的代码
public class HelloWorld {
public static String method1(String[] array){return ""+array.length;}
public static String method2(String... array){return ""+array.length;}
public static void main(String args[]) {
System.out.println(method1(new String[]{"test"})); //allowed
//System.out.println(method1("test")); Not allowed
System.out.println(method2(new String[]{"test"})); //allowed
System.out.println(method2("test")); //allowed
}
}
当我这样做时
javap HelloWorld
C:\Users\athakur\JavaProjectWorkspace\HelloWorld\bin\test>javap HelloWorld
Compiled from "HelloWorld.java"
public class test.HelloWorld extends java.lang.Object{
public test.HelloWorld();
public static java.lang.String method1(java.lang.String[]);
public static java.lang.String method2(java.lang.String[]);
public static void main(java.lang.String[]);
}
因此,根据类文件
method1
和 method2
采用相同的数组参数。那么为什么他们可以接受的输入存在差异呢?
就像
method1
不能接受简单的 String
输入,而 vararg 可以接受变量 String
输入以及数组?
因此,根据类文件 method1 和 method2 采用相同的数组参数。
是的,除了类文件中有额外的元数据来指示
method2
的参数是可变参数参数。这实际上只是参数上的额外数据 - 仅此而已。
Parameter.isVarArgs
通过反射来检测它。
这意味着编译器愿意接受这样的调用:
method2("test")
并将其隐式转换为
method2(new String[] { "test" })
您并不总是想要这种行为,因此必须使用 varargs 语法在参数上显式指定它。
我怀疑您还使用了稍旧版本的
javap
,如果它没有向您显示两个方法声明之间的差异。在我的版本(Java 8)上我得到:
public static java.lang.String method1(java.lang.String[]);
public static java.lang.String method2(java.lang.String...);
唯一的区别是方法的签名可能具有可变数量的参数,而不是数组参数,您只能传递一个参数。无论如何,将数组作为 vararg 传递给方法是被接受的并将在内部使用。另一方面,可变参数将被转换为数组并在那里使用。
当您将数组作为参数传递给这两种方法时。为了回答你的问题,我们不要使用数组
System.out.println(method2("test")); //allowed
System.out.println(method2("test","test2")); //allowed
正如您所注意到的,只有当您使用 vararg 参数时,这才有效。