Java,参数中有3个点

Vik*_*ram 781 java variadic-functions

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

public void myMethod(String... strings){
    // method body
}
Run Code Online (Sandbox Code Playgroud)

kis*_*swa 933

这意味着可以传递零个或多个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"});
Run Code Online (Sandbox Code Playgroud)

重要说明:以这种方式传递的参数始终是一个数组 - 即使只有一个.确保在方法体中以这种方式对待它.

重要说明2:获取的参数...必须是方法签名中的最后一个.所以,myMethod(int i, String... strings)没关系,但myMethod(String... strings, int i)不行.

感谢Vash在评论中的澄清.

  • 你错了,在"一个或多个"中,我们可以指定0或更多的varargs,这必须始终是方法中的最后一个参数.方法x(String ... params)可以调用为x()或方法y(String pram,String ... params)可以调用为y("1") (110认同)
  • 因为它们是可选的.由开发人员决定使用可选参数来正确实现该方法以处理其中的零个或多个. (11认同)
  • 我希望这是否也行得通。myMethod(“一个”,“两个”,“三个”,新的String [] {“ a”,“ b”,“ c”“})); (2认同)
  • 为什么允许给方法0提供参数?这很可能导致ArrayIndexOutOfBoundsException。现在,您始终必须考虑到这种情况。 (2认同)

Cri*_*ian 116

该功能称为varargs,它是Java 5中引入的一个功能.它意味着该函数可以接收多个String参数:

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

然后,您可以将Stringvar用作数组:

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]
    }
}
Run Code Online (Sandbox Code Playgroud)

这个答案大量借鉴了基斯瓦和洛伦佐的......以及格拉芬的评论.

  • 当代码命中字节码时,它*是一个数组.其他所有内容都是编译器支持的语法. (13认同)
  • @Graph最好编辑你的答案并使其更正确而不是单独留下.如果另一个答案是你改进的源头,那么它就是如此.至少他是诚实的(并且我认为他赞成了帮助他的其他答案......对吗?). (3认同)

SIW*_*SIW 19

这是Varargs :)

变长参数的缩写是一种允许该方法接受可变数量的参数(零或更多)的功能.使用varargs,创建需要使用可变数量参数的方法变得非常简单.Java 5中添加了变量参数的功能.

varargs的语法

在数据类型之后,vararg由三个省略号(三个点)进行处理,其一般形式为

return_type method_name(data_type ... variableName){
}  
Run Code Online (Sandbox Code Playgroud)

需要varargs

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

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

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 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
Run Code Online (Sandbox Code Playgroud)

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

varargs的限制

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

void displayValues(int a, int b, int … values) // OK
   void displayValues(int a, int b, int … values, int c) // compiler error
Run Code Online (Sandbox Code Playgroud)

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

void displayValues(int a, int b, int … values, int … moreValues) // Compiler error
Run Code Online (Sandbox Code Playgroud)

重载varargs方法

可以重载采用varargs参数的方法.Varargs方法可以重载 -

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

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 
Run Code Online (Sandbox Code Playgroud)

Varargs和重载模糊

在某些情况下,当我们重载varargs方法时,调用可能是不明确的.我们来看一个例子吧

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();
 }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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


lor*_*ova 13

这是传递varargs(变量号参数)的Java方法.

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

int printf(const char * format, ...);
Run Code Online (Sandbox Code Playgroud)

但是以类型安全的方式:每个参数都必须符合指定的类型(在您的示例中,它们应该是全部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");
   }
}
Run Code Online (Sandbox Code Playgroud)

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


小智 11

可以说,它是语法糖的一个例子,因为它无论如何都被实现为一个数组(这并不意味着它没用) - 我更喜欢传递一个数组以保持清晰,并且还使用给定类型的数组声明方法.相反,它是一种意见,而不是一种答案.


Mr.*_*r.Q 7

同样要说明一点,重要的是要知道 var-arg 参数仅限于一个,并且不能有多个 var-art 参数。例如这是非法的:

public void myMethod(String... strings, int ... ints){
// method body
}
Run Code Online (Sandbox Code Playgroud)