参数类型旁边的3个点在Java中意味着什么?

以下方法中String后面的3个点是什么意思?

public void myMethod(String... strings) {// method body}
525251 次浏览

该特性称为varargs,它是Java5中引入的特性。这意味着函数可以接收多个String参数:

myMethod("foo", "bar");myMethod("foo", "bar", "baz");myMethod(new String[]{"foo", "var", "baz"}); // you can even pass an array

然后,您可以使用String var作为数组:

public void myMethod(String... strings) {for (String whatever : strings) {// do what ever you want}
// the code above is equivalent tofor (int i = 0; i < strings.length; i++) {// classical for. In this case you use strings[i]}}

这个答案大量借鉴了Kiswa和Lorenzo的……以及Graphain的评论。

这意味着零个或多个String对象(或它们的单个数组)可以作为该方法的参数传递。

请参阅“任意数量的参数”部分:http://java.sun.com/docs/books/tutorial/java/javaOO/arguments.html#varargs

在您的示例中,您可以将其称为以下任何一种:

myMethod(); // Likely useless, but possiblemyMethod("one", "two", "three");myMethod("solo");myMethod(new String[]{"a", "b", "c"});

重要提示:以这种方式传递的参数始终是一个数组-即使只有一个。确保您在方法主体中以这种方式处理它。

重要提示2:获得...的参数必须是方法签名中的最后一个。所以,myMethod(int i, String... strings)可以,但myMethod(String... strings, int i)不行。

感谢Vash在评论中的澄清。

这是传递varargs(可变数字参数)的Java方法。

如果你熟悉C,这类似于...语法使用它的printf函数:

int printf(const char * format, ...);

但是以类型安全的方式:每个参数都必须符合指定的类型(在您的示例中,它们应该都是String)。

这是一个如何使用varargs的简单示例:

class VarargSample {
public static void PrintMultipleStrings(String... strings) {for( String s : strings ) {System.out.println(s);}}
public static void main(String[] args) {PrintMultipleStrings("Hello", "world");}}

...参数实际上是一个数组,因此您可以传递String[]作为参数。

可以说,它是语法糖的一个例子,因为它无论如何都是作为数组实现的(这并不意味着它毫无用处)-我更喜欢传递数组以保持清晰,并使用给定类型的数组声明方法。

只要把它想象成C#中的关键字params,如果你来自那个背景:)

一种非常常见的方式来查看三个点的使用示例,它存在于android异步任务中最著名的方法之一(由于RXJAVA,今天没有太多使用,更不用说Google架构组件了),你可以找到数千个搜索这个术语的例子,理解并永远不会忘记三个点的含义的最好方法是,它们表达了一个…怀疑…就像在通用语言中一样。即不清楚必须传递的参数数量,可能是0,可能是1可能更多(数组)…

同样为了阐明一些问题,重要的是要知道var-arg参数仅限于一个,并且你不能有多个var-art参数。例如,这是illigal:

public void myMethod(String... strings, int ... ints){// method body}

是瓦格斯:)

varargs是可变长度参数的缩写,它允许方法接受可变数量的参数(零或更多)。使用varargs,创建需要可变数量参数的方法变得很简单。可变参数的特性已在Java5中添加。

变体语法

vararg由数据类型后的三个省略号(三个点)固定,其一般形式为

return_type method_name(data_type ... variableName){}

需要瓦拉格斯

在Java5之前,如果需要可变数量的参数,有两种方法可以处理它

如果方法可以接受的最大参数数很小并且已知,则可以创建该方法的重载版本。如果方法可以接受的最大参数数量很大或/且未知,那么方法是将这些参数放入数组中并将它们传递给以数组为参数的方法。这两种方法容易出错——每次都构造一个参数数组并且难以维护——因为添加新参数可能会导致编写一个新的重载方法。

varargs的优点

提供了一个更简单的选择。无需编写重载方法,代码更少。

varargs的例子

public class VarargsExample {public void displayData(String ... values){System.out.println("Number of arguments passed " + values.length);for(String s : values){System.out.println(s + " ");}}
public static void main(String[] args) {VarargsExample vObj = new VarargsExample();// four argsvObj.displayData("var", "args", "are", "passed");//three argsvObj.displayData("Three", "args", "passed");// no-argvObj.displayData();}}Output
Number of arguments passed 4varargsarepassedNumber of arguments passed 3ThreeargspassedNumber of arguments passed 0

从程序中可以看出,这里使用长度来查找传递给方法的参数数量。这是可能的,因为varargs作为数组隐式传递。任何作为varargs传递的参数都存储在一个数组中,该数组由给varargs的名称引用。在这个程序中,数组名称是值。另请注意,方法以不同数量的参数调用,首先调用四个参数,然后是三个参数,然后是零参数。所有这些调用都由采用varargs的同一方法处理。

用varargs限制

在方法中可以有其他带有varargs参数的参数,但是在这种情况下,varargs参数必须是方法声明的最后一个参数。

void displayValues(int a, int b, int … values) // OKvoid displayValues(int a, int b, int … values, int c) // compiler error

varargs的另一个限制是必须只有一个varargs参数。

void displayValues(int a, int b, int … values, int … moreValues) // Compiler error

重载varargs方法

可以重载接受varargs参数的方法。Varargs方法可以通过-

重载

它的vararg参数的类型可以不同。添加其他参数。重载varargs方法示例

public class OverloadingVarargsExp {// Method which has string vararg parameterpublic void displayData(String ... values){System.out.println("Number of arguments passed " + values.length);for(String s : values){System.out.println(s + " ");}}
// Method which has int vararg parameterpublic void displayData(int ... values){System.out.println("Number of arguments passed " + values.length);for(int i : values){System.out.println(i + " ");}}
// Method with int vararg and one more string parameterpublic void displayData(String a, int ... values){System.out.println(" a " + a);System.out.println("Number of arguments passed " + values.length);for(int i : values){System.out.println(i + " ");}}
public static void main(String[] args) {OverloadingVarargsExp vObj = new OverloadingVarargsExp();// four string argsvObj.displayData("var", "args", "are", "passed");
// two int argsvObj.displayData(10, 20);
// One String param and two int argsvObj.displayData("Test", 20, 30);}}Output
Number of arguments passed 4varargsarepassed
Number of arguments passed 21020
a TestNumber of arguments passed 22030

Varargs和重载歧义

在某些情况下,调用可能会有歧义,而我们重载了varargs方法。举个例子

public class OverloadingVarargsExp {// Method which has string vararg parameterpublic void displayData(String ... values){System.out.println("Number of arguments passed " + values.length);for(String s : values){System.out.println(s + " ");}}
// Method which has int vararg parameterpublic void displayData(int ... values){System.out.println("Number of arguments passed " + values.length);for(int i : values){System.out.println(i + " ");}}
public static void main(String[] args) {OverloadingVarargsExp vObj = new OverloadingVarargsExp();// four string argsvObj.displayData("var", "args", "are", "passed");
// two int argsvObj.displayData(10, 20);
// This call is ambiguousvObj.displayData();}}

在这个程序中,当我们在没有任何参数的情况下调用displayData()方法时,它会抛出错误,因为编译器不确定这个方法调用是displayData(String ... values)还是displayData(int ... values)

同样,如果我们有重载的方法,其中一个有一种类型的vararg方法,另一个方法有一个参数和相同类型的vararg参数,那么我们也有歧义-作为Exp-displayData(int ... values)displayData(int a, int ... values)

这两个重载的方法总是有歧义的。

语法:(三个点…)-->意味着我们可以添加零个或多个对象传递参数或传递对象类型的数组。

public static void main(String[] args){}public static void main(String... args){}

定义:1)Object…参数只是对Object数组的引用。

2)('String[]'或String…)它能够处理任意数量的字符串对象。在内部,它使用引用类型对象的数组。

i.e. Suppose we pass an Object array to the ... argument - will the resultant argument value be a two-dimensional array - because an Object[] is itself an Object:

3)如果你想用一个参数调用方法,而它恰好是一个数组,你必须显式地包装它

another. method(new Object[]{array});ORmethod((Object)array), which will auto-wrap.

应用:它主要用于参数数量是动态的(运行时知道的参数数量)和覆盖。一般规则-在方法中,我们可以传递任何类型和任意数量的参数。我们不能在任何特定参数之前添加对象(…)参数。即

void m1(String ..., String s) this is a wrong approach give syntax error.void m1(String s, String ...); This is a right approach. Must always give last order prefernces.