Java,参数中有3个点

时间:2010-07-01 14:27:49

标签: java variadic-functions

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

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

12 个答案:

答案 0 :(得分:879)

这意味着零个或多个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在评论中作出澄清。

答案 1 :(得分:108)

该功能称为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]
    }
}

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

答案 2 :(得分:12)

这是传递 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[]作为参数。

答案 3 :(得分:12)

它的Varargs :)

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

varargs的语法

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

return_type method_name(data_type ... variableName){
}  

需要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

从程序中可以看出,此处使用长度来查找传递给方法的参数数量。这是可能的,因为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

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 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 

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();
 }
}

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

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

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

答案 4 :(得分:11)

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

答案 5 :(得分:4)

如果您来自C#,请将其视为C#中的关键字params:)

答案 6 :(得分:4)

同样为了解释一下,重要的是要知道var-arg参数仅限于一个,你不能拥有几个var-art params。例如,这是illigal:

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

答案 7 :(得分:1)

一种非常常见的方式来查看使用三个点的明确示例,它存在于android AsyncTask中最着名的方法之一(由于RXJAVA,今天使用不太多,而不是提到谷歌架构组件),你可以找到成千上万的例子来搜索这个术语,理解并永远不会忘记这三个点的意思的最佳方式是它们表达了......怀疑......就像在通用语言。也就是说,不清楚必须传递的参数数量,可能是0,可能是1可能更多(一个数组)......

答案 8 :(得分:1)

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);

        }
        }
        }

答案 9 :(得分:0)

除了其他写得很好的答案之外,我发现varagrs的一个优点是,当我将数组作为参数类型调用方法时,它消除了创建数组的麻烦;添加元素,然后发送它。取而代之的是,我可以使用所需的任意多个值来调用该方法。从零到很多。

答案 10 :(得分:-1)

  • 表示零个或多个相同数据类型的参数。
  • 它必须是构造函数或函数的最后一个参数。
  • 我们在相应的构造函数中只能有一个此类型参数 或功能。

示例1:

public class quest1 {

    public quest1(String... mynum) {
        System.out.println("yee haa");
    }

    public static void main(String[] args) {
        quest1 q=new quest1();

        quest1 q1=new quest1("hello");

    }
}

示例2:

public class quest1 {

    public quest1(int... at) {
        System.out.println("yee haa");
    }

    public quest1(String... at) {
        System.out.println("yee haa");
    }

    public static void main(String[] args) {
        quest1 q=new quest1("value");

        quest1 q1=new quest1(1);

    }

    public void name(String ... s) {

    }
}

输出:

yee haa

yee haa

答案 11 :(得分:-1)

语法: (三点...)->表示我们可以添加零个或多个对象,以传递参数或类型为object的数组。

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

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

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}); 
OR 
method((Object)array), which will auto-wrap.

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

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.