Java中的数组参数声明语法"..."是如何工作的?

57

我已经写了一段时间的Java代码,今天遇到了以下声明:

public static void main(String... args) {

}
请注意数组声明中的“点点点”,而不是通常的方括号[]。很明显,它可以工作。事实上,我写了一个小测试并验证了它可以工作。因此,我查看了Java语法,并没有找到这种参数声明语法。
所以,对于那些专家们,这是如何工作的?它是否属于语法的一部分?另外,虽然我可以像这样声明函数,但我无法在函数体内像这样声明一个数组。
无论如何,你知道有没有任何地方有这个文档记录。这只是好奇,也许不值得投入太多时间,但我被难住了。

1
还要考虑https://dev59.com/1HRC5IYBdhLWcg3wYP6h#315853 - Johannes Schaub - litb
10个回答

43

33
请查看Java语言规范第三版第8章(类)。其中有这样一段话:

如果最后一个形式参数是类型为T的可变元参数,它被认为定义了类型为T[]的形式参数。该方法则成为可变元方法。否则,它是一个固定元方法。可变元方法的调用可能包含比形式参数更多的实际参数表达式。所有不对应于可变元参数之前的形式参数的实际参数表达式将被计算并存储到数组中,然后传递给方法调用(§15.12.4.2)。

基本上,任何方法调用的最后一个参数都可以有T...。如果有这个,则会转换为T[]
所以,基本上你拥有一种繁琐的方式来复制更传统的方法。
String[] args

1
另外,考虑到数组参数和可变参数的签名不同,这会如何工作? - nanofarad

23


7

这是所谓的可变参数语法。在方法体中,您可以像读取数组一样读取members参数 - 实际上,它实际上就是一个数组。

然而,神奇的部分在于调用方法。在引入varargs语法之前,您会这样调用方法:

setMembers(new Members[] {member1, member2, member3});

使用新的可变参数语法,您不再需要显式创建数组,可以直接传递以下内容:

setMembers(member1, member2, member3);

这意味着,varargs参数必须是方法中的最后一个参数。因此,像这样的写法是不允许的:
void setMembers(Member ... members, String memberType);

总结一下:这只是一点语法糖而已。我对Java编译器的内部工作不是很了解,但我非常确定调用接受varargs参数的方法的方法将被重建为构建给定类型数组的方法。


4
您可能想要阅读有关Java中使用可变参数(或varargs)的 文章

3
这意味着你可以向setMembers()方法传递零个或多个Member对象。在setMembers方法中,members将具有数组语义。

3

2
可变参数。可以有0个或多个字符串参数。
函数可以将参数作为字符串数组访问。

1
好的,我想我明白了,就像这样: string x="hi" string y="you" printString(x,y);public void printString(String... greetings){ for(int x=0;x<greetings.length;x++) System.out.println(greetings[x]); }这会打印出“hi you”,对吗? - Winter
2
是的,确切地说是 "hi<newline>you<newline>"。你也可以使用 "for (String s: greetins) ..." 这种更好看的写法 :) - Jan Zyka

0

这意味着该方法接受可变数量的字符串参数。这些参数被视为数组,并按照它们传递的顺序通过下标访问。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接