你什么时候在Java中使用varargs?

Har*_*nce 190 java variadic-functions

我害怕varargs.我不知道该怎么用它们.

另外,让人们通过他们想要的许多论点是危险的.

什么是上下文的一个例子,它将是一个使用它们的好地方?

And*_*ite 150

Varargs 对于需要处理不确定数量的对象的任何方法都很有用.一个很好的例子是String.format.格式字符串可以接受任意数量的参数,因此您需要一种机制来传入任意数量的对象.

String.format("This is an integer: %d", myInt);
String.format("This is an integer: %d and a string: %s", myInt, myString);
Run Code Online (Sandbox Code Playgroud)

  • 数组参数也可以接收不确定数量的对象,但 varargs 参数在调用时提供更大的灵活性和便利性。您可以编写代码来构建一个数组并传递它,或者当您选择在 varargs 参数中接收它时,您可以让 Java 为您完成。 (4认同)

jfp*_*ret 78

一个好的经验法则是:

"对任何需要T数组(无论T类型)作为输入的方法(或构造函数)使用varargs".

这将使这些方法的调用更容易(不需要这样做new T[]{...}).

您可以扩展此规则以包含带List<T>参数的方法,前提是此参数仅用于输入(即,该方法不修改列表).

另外,我会避免使用,f(Object... args)因为它的API 会出现不明确的编程方式.

在示例方面,我在DesignGridLayout中使用它,我可以JComponent在一个调用中添加几个s:

layout.row().grid(new JLabel("Label")).add(field1, field2, field3);
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,add()方法定义为add(JComponent... components).

最后,这些方法的实现必须注意它可以用空的vararg调用它!如果你想强加至少一个参数,那么你必须使用一个丑陋的技巧,例如:

void f(T arg1, T... args) {...}
Run Code Online (Sandbox Code Playgroud)

我认为这个技巧很难看,因为该方法的实现不如仅仅T... args在其参数列表中那么简单.

希望这有助于澄清关于varargs的观点.

  • 好吧,一个好的API的目的是尽可能早地防止滥用,所以在可能的编译时,因此建议`void f(T arg1,T ... args)`始终确保它永远不会被调用没有参数,无需等到运行时. (24认同)

小智 34

我经常使用varargs输出到日志以进行调试.

几乎我的应用程序中的每个类都有一个方法debugPrint():

private void debugPrint(Object... msg) {
    for (Object item : msg) System.out.print(item);
    System.out.println();
}
Run Code Online (Sandbox Code Playgroud)

然后,在类的方法中,我有如下调用:

debugPrint("for assignment ", hwId, ", student ", studentId, ", question ",
    serialNo, ", the grade is ", grade);
Run Code Online (Sandbox Code Playgroud)

当我对我的代码正常工作感到满意时,我会在debugPrint()方法中注释掉代码,这样日志就不会包含太多无关和不需要的信息,但我可以将对debugPrint()的各个调用取消注释.稍后,如果我发现了一个错误,我只需取消注释debugPrint()代码,并重新激活我对debugPrint()的所有调用.

当然,我可以轻易地避开varargs并执行以下操作:

private void debugPrint(String msg) {
    System.out.println(msg);
}

debugPrint("for assignment " + hwId + ", student " + studentId + ", question "
    + serialNo + ", the grade is " + grade);
Run Code Online (Sandbox Code Playgroud)

但是,在这种情况下,当我注释掉debugPrint()代码时,服务器仍然需要在每次调用debugPrint()时连接所有变量的麻烦,即使对结果字符串没有任何处理.但是,如果我使用varargs,服务器只有在意识到它不需要它们之前才必须将它们放在一个数组中.节省了很多时间.

  • 您可以在超类中实现调试方法,以使用反射打印任何对象. (4认同)

Sar*_*van 12

当我们不确定要在方法中传递的参数数量时,可以使用Varargs.它在后台创建一个未指定长度的参数数组,这样的参数可以在运行时被视为一个数组.

如果我们有一个重载的方法来接受不同数量的参数,那么我们可以简单地使用varargs概念,而不是不同地重载方法.

此外,当参数的类型将发生变化时,使用"Object ... test"将大大简化代码.

例如:

public int calculate(int...list) {
    int sum = 0;
    for (int item : list) {
        sum += item;
    }
    return sum;
}
Run Code Online (Sandbox Code Playgroud)

这里间接地将int类型(list)数组作为参数传递,并在代码中被视为数组.

为了更好地理解,请点击此链接(这有助于我清楚地理解这个概念):http: //www.javadb.com/using-varargs-in-java

PS:即使我不喜欢使用varargs,我还是不知道如何使用varargs.但现在我已经习惯了.正如所说:"我们坚持已知,害怕未知",所以只要尽可能多地使用它,你也会开始喜欢它:)

  • C#等价的varargs是"params".它也做同样的事情并接受可变数量的参数.请参阅此内容以获得更好的理解:http://www.dotnetperls.com/params (4认同)

Aru*_*ash 11

Varargs是java 1.5版中添加的功能.

为什么要用这个?

  1. 如果,您不知道方法传递的参数数量,该怎么办?
  2. 如果,您想要向方法传递无限数量的参数,该怎么办?

这是怎么回事?

它使用给定的参数创建一个数组并将数组传递给方法.

示例:

public class Solution {



    public static void main(String[] args) {
        add(5,7);
        add(5,7,9);
    }

    public static void add(int... s){
        System.out.println(s.length);
        int sum=0;
        for(int num:s)
            sum=sum+num;
        System.out.println("sum is "+sum );
    }

}
Run Code Online (Sandbox Code Playgroud)

输出:

2

总和是12

3

总和是21


Thi*_*ilo 5

我也有与varargs相关的恐惧:

如果调用者将显式数组传递给方法(而不是多个参数),您将收到对该数组的共享引用.

如果需要在内部存储此数组,可能需要首先克隆它,以避免调用者以后能够更改它.

 Object[] args = new Object[] { 1, 2, 3} ;

 varArgMethod(args);  // not varArgMethod(1,2,3);

 args[2] = "something else";  // this could have unexpected side-effects
Run Code Online (Sandbox Code Playgroud)

虽然这与传入任何状态可能稍后改变的任何类型的对象没有什么不同,因为数组通常是(在使用多个参数而不是数组的调用的情况下)由编译器在内部创建的一个新的,您可以安全地使用,这肯定是出乎意料的行为.

  • 我认为您的用例示例一般来说并非不可能.有人可能会说你的API不应该以这种方式使用输入数组,如果是这样,它必须记录它. (5认同)
  • 你永远不会知道......特别是当参数的数量在调用方面没有硬编码,但也被收集到循环中的列表中时,传入一个数组并不是那么罕见. (2认同)
  • @thetoolman:我不认为这是可能的.它将被视为一种重复的方法. (2认同)