什么时候在Java中使用varargs?

什么时候在Java中使用varargs?,java,variadic-functions,Java,Variadic Functions,我怕瓦拉格人。我不知道用它们干什么 此外,让人们随意传递争论是很危险的 什么样的上下文是使用它们的好地方?Varargs对于任何需要处理数量不确定的对象的方法都很有用。一个很好的例子是。格式字符串可以接受任意数量的参数,因此需要一种机制来传入任意数量的对象 String.format("This is an integer: %d", myInt); String.format("This is an integer: %d and a string: %s", myInt, myString)

我怕瓦拉格人。我不知道用它们干什么

此外,让人们随意传递争论是很危险的

什么样的上下文是使用它们的好地方?

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

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

我经常将varargs用于可以接受某种筛选器对象的构造函数。例如,我们基于Hadoop的系统的很大一部分是基于一个映射器的,该映射器处理JSON项的序列化和反序列化,并应用多个处理器,每个处理器接收一个内容项,然后修改并返回它,或者返回null以拒绝它。

一个好的经验法则是:

“对任何需要T数组(不管T是什么类型)作为输入的方法(或构造函数)使用varargs”。

这将使对这些方法的调用更容易(无需执行
newt[]{…}

您可以扩展此规则以包括具有
列表
参数的方法,前提是此参数仅用于输入(即,列表不由该方法修改)

此外,我会避免使用
f(Object…args)
,因为它会滑向一种API不清晰的编程方式

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

layout.row().grid(new JLabel("Label")).add(field1, field2, field3);
在上面的代码中,add()方法被定义为
add(JComponent…components)

最后,这些方法的实现必须考虑这样一个事实,即可以使用空vararg调用它!如果你想强加至少一个论点,那么你必须使用一个丑陋的伎俩,例如:

void f(T arg1, T... args) {...}
我认为这个把戏很难看,因为这种方法的实施将比直接使用<代码>……要简单得多。参数列表中的args


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

我也有一种与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

虽然这与传入任何类型的对象(其状态可能会在以后更改)并没有什么区别,但因为数组通常是由编译器内部创建的新数组(如果调用的是多个参数而不是数组),您可以安全地使用,这当然是意外的行为。

为了调试的目的,我经常使用varargs输出到日志

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

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

debugPrint("for assignment ", hwId, ", student ", studentId, ", question ",
    serialNo, ", the grade is ", grade);
当我对代码正常工作感到满意时,我会在debugPrint()方法中注释掉代码,这样日志就不会包含太多无关和不需要的信息,但我可以不注释对debugPrint()的单独调用。稍后,如果发现bug,我只需取消对debugPrint()代码的注释,所有对debugPrint()的调用都会重新激活

当然,我也可以很容易地避开varargs,而是做以下事情:

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

debugPrint("for assignment " + hwId + ", student " + studentId + ", question "
    + serialNo + ", the grade is " + grade);

但是,在本例中,当我注释掉debugPrint()代码时,服务器仍然要经历将每次调用debugPrint()中的所有变量串联在一起的麻烦,即使对结果字符串没有做任何处理。但是,如果我使用varargs,服务器只需将它们放入一个数组中,就可以意识到它不需要它们。节省了大量时间。

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

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

另外,当参数的类型发生变化时,使用“对象…测试”将大大简化代码

例如:

public int calculate(int...list) {
    int sum = 0;
    for (int item : list) {
        sum += item;
    }
    return sum;
}
这里,int类型的数组(list)作为参数传递,并在代码中作为数组处理

为了更好地理解,请点击这个链接(它帮助我更清楚地理解这个概念):

附言:当我没有使用varargs时,我甚至都害怕使用它。但现在我已经习惯了。
正如人们所说:“我们执着于已知,害怕未知”,所以只要尽可能多地使用它,你也会开始喜欢它:)

Varargs是java 1.5版中添加的特性

为什么要用这个?

  • 如果您不知道要为一个方法传递的参数数量,该怎么办
  • 如果要向方法传递无限数量的参数,该怎么办
  • 这是如何工作的?

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

    例如:

    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 );
        }
    
    }
    
    输出:

    二,

    总数是12

    三,


    在Var Args的Java文档中,sum是21,Var Args的用法非常清楚:

    关于用法,它说:

    “那么什么时候应该使用varargs? 作为客户机,无论API提供什么,您都应该利用它们。核心API中的重要用途包括反射、消息格式和新的printf功能。 作为一名API设计师,您应该谨慎地使用它们,只有在好处确实令人信服时才可以使用。 一般来说,您不应该重载varargs方法,否则程序员将很难确定调用哪个重载。”

    我不明白为什么它会“危险”。这并不比使用不同参数多次调用方法更危险。你对t有顾虑吗
    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 );
        }
    
    }