【问题标题】:What do 3 dots next to a parameter type mean in Java?Java中参数类型旁边的3个点是什么意思?
【发布时间】:2011-03-10 16:18:51
【问题描述】:

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

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

【问题讨论】:

    标签: java variadic-functions


    【解决方案1】:

    该功能称为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 equivalent to
        for( int i = 0; i < strings.length; i++){
            // classical for. In this case you use strings[i]
        }
    }
    

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

    【讨论】:

    • 当代码命中字节码时,它一个数组。其他一切都是编译器支持的语法。
    • 如果我正确阅读了编辑,这个答案大量借鉴了 kiswa 和 Lorenzo 的答案。
    • @Graph '最好编辑你的答案并使其更正确,而不是不理会它。如果另一个答案是你改进的源泉,那就去吧。至少他对此是诚实的(我认为他赞成其他对他有帮助的答案......对吧?)。
    • @在我指出这件事之后他会诚实吗?感谢收看。
    【解决方案2】:

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

    【讨论】:

    • 我希望这也能奏效。 myMethod("one","two","three", new String[] {"a","b","c""});
    • 为什么允许给方法0参数?这很可能会导致 ArrayIndexOutOfBoundsException。现在您必须始终考虑这种情况。
    • 因为它们是可选的。这取决于决定使用可选参数来正确实现处理零个或多个参数的方法的开发人员。
    • @OlleSöderström 另一个原因是形式参数在编译时被转换为数组。这意味着传入一个数组会产生相同的结果。由于在编译时不知道数组的长度,因此可以通过简单地调用someMethod(new SomeType[] { }) 来绕过传递至少一个元素的限制。那将是一个黑客,不是吗?
    • 在不会发生混淆的情况下,是否存在可变参数不是最后一个并且可以使用更多非 kw 参数的语言?
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

        • 我是一名 C# 程序员。
        【解决方案6】:

        一种非常常见的方式来查看使用三个点的清晰示例,它出现在 android AsyncTask 中最著名的方法之一中(由于 RXJAVA,今天没有使用太多,更不用说Google Architecture components),您可以找到数千个搜索该术语的示例,而最好的理解和永远不会忘记三个点的含义的方法是它们表达了......怀疑......就像在通用语言中一样.即不清楚必须传递的参数数量,可能是0,可能是1,可能是更多(一个数组)......

        【讨论】:

          【解决方案7】:

          另外,为了阐明一些观点,重要的是要知道 var-arg 参数仅限于一个,并且您不能有多个 var-art 参数。例如这是非法的:

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

          【讨论】:

            【解决方案8】:

            这是可变参数 :)

            可变长度参数的 varargs 缩写是允许方法接受可变数量的参数(零个或多个)的功能。使用可变参数,创建需要可变数量参数的方法变得很简单。 Java 5 增加了变量参数的功能。

            可变参数的语法

            可变参数由数据类型后面的三个省略号(三个点)分隔,其一般形式为

            return_type method_name(data_type ... variableName){
            }  
            

            需要可变参数

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

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

            可变参数的优点

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

            可变参数示例

            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
            

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

            可变参数的限制

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

            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 方法可以被 -

            重载

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

            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 方法时,调用可能会产生歧义。 我们来看一个例子

            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)

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

            【讨论】:

              【解决方案9】:

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

              【讨论】:

                【解决方案10】:

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

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

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

                2) ('String []' or 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.   
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2015-11-11
                  • 2022-07-21
                  • 2014-04-18
                  • 1970-01-01
                  • 2019-12-22
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多