Java,参数中有3个点

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

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

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

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

在你的例子中,你可以把它称为以下任何一个:

 myMethod(); // Likely useless, but possible myMethod("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 5中引入的一个特性。它意味着函数可以接收多个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 is equivalent to for( int i = 0; i < strings.length; i++){ // classical for. In this case you use strings[i] } } 

这个答案很大程度上借鉴了kiswa和Lorenzo的…以及Graphain的评论。

这是通过可变参数 (可变数字参数)的Java方法。

如果你熟悉C语言,这与使用printf函数的语法类似:

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

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

这是一个如何使用可变参数的简单示例:

 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[]作为参数。

可以说,这是一个语法糖的例子,因为它实际上是作为一个数组实现的(这并不意味着它是无用的) – 我更喜欢传递一个数组来保持清晰,并且还用给定types的数组声明方法。 而是一个意见,而不是一个答案,但。

可变长参数的可变参数是一个允许方法接受可变数量的参数(零个或多个)的特性。 使用可变参数很容易创build需要variables数量的参数的方法。 Java 5中增加了可变参数的特性。

可变参数的语法

在数据types之后,可变参数由三个省略号(三个点)分隔,其一般forms为

 return_type method_name(data_type ... variableName){ } 

需要可变参数

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

如果参数的最大数量,一个方法可以采取的是小的和已知的,那么可以创build方法的重载版本。 如果一个方法可以采用的最大参数数目很大或/和未知,那么方法是将这些参数放在一个数组中,并将它们传递给一个将数组作为参数的方法。 这两种方法很容易出错 – 每次构build一个参数数组并且难以维护 – 因为增加新的参数可能导致编写新的重载方法。

可变参数的优点

提供了一个更简单的选项。 由于不需要编写重载方法,所以代码更less。

可变参数的例子

 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 args vObj.displayData("var", "args", "are", "passed"); //three args vObj.displayData("Three", "args", "passed"); // no-arg vObj.displayData(); } } Output Number of arguments passed 4 var args are passed Number of arguments passed 3 Three args passed Number of arguments passed 0 

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

可变参数的限制

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

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

可变参数的另一个限制是只能有一个可变参数。

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

重载可变参数方法

可以重载一个采用可变参数的方法。 Varargs方法可以被重载 –

其可变参数的types可以不同。 通过添加其他参数。 重载可变参数方法的例子

 public class OverloadingVarargsExp { // Method which has string vararg parameter public 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 parameter public 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 parameter public 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 args vObj.displayData("var", "args", "are", "passed"); // two int args vObj.displayData(10, 20); // One String param and two int args vObj.displayData("Test", 20, 30); } } Output Number of arguments passed 4 var args are passed Number of arguments passed 2 10 20 a Test Number of arguments passed 2 20 30 

可变参数和超载模糊

在某些情况下,调用可能不明确,而我们已经重载了可变参数方法。 我们来看一个例子

 public class OverloadingVarargsExp { // Method which has string vararg parameter public 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 parameter public 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 args vObj.displayData("var", "args", "are", "passed"); // two int args vObj.displayData(10, 20); // This call is ambiguous vObj.displayData(); } } 

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

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

这两个重载的方法总是含糊不清。

另外为了说明一下,知道var-arg参数限制为1是很重要的,你不能有几个var-art参数。 例如,这是illigal:

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

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

String...String[]相同

 import java.lang.*; public class MyClassTest { //public static void main(String... args) { public static void main(String[] args) { for(String str: args) { System.out.println(str); } } } 

一个真正常见的方式来看到一个清楚的例子,使用三个点,它是在Android的AsyncTask (今天是不是因为太多的RXJAVA,更不用说Google架构组件)使用最有名的方法之一,你可以find成千上万的例子来寻找这个词,理解和再也不会忘记这三个点的意义的最好方法就是他们expression一个……疑问……就像在通用语言中一样。 即不清楚必须通过的参数的数量,可能是0,可能是1可能更多(一个数组)… … –