在Java中什么时候使用可变参数?

我害怕变参数。我不知道要用它们做什么。

另外,让人们随意争论是很危险的。

有什么上下文的例子可以很好地使用它们?

169668 次浏览

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

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

我经常使用可变参数作为构造函数,这些构造函数可以接受某种过滤器对象。例如,我们基于Hadoop的系统的很大一部分是基于Mapper的,Mapper处理对JSON的项的序列化和反序列化,并应用了许多处理器,每个处理器获取一个内容项,要么修改并返回它,要么返回null以拒绝。

一个好的经验法则是:

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

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

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

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

就示例而言,我在DesignGridLayout中使用了它,在那里我可以在一次调用中添加几个__abc0:

layout.row().grid(new JLabel("Label")).add(field1, field2, field3);

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

最后,这种方法的实现必须注意这样一个事实,即它可能被一个空变量调用!如果你想要强加至少一个论点,那么你必须使用一个丑陋的技巧,例如:

void f(T arg1, T... args) {...}

我认为这个技巧很难看,因为这个方法的实现比在它的参数列表中只有T... args要简单得多。

希望这有助于澄清关于可变参数的观点。

我也有一种与内变性有关的恐惧:

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

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

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


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


args[2] = "something else";  // this could have unexpected side-effects

虽然这与传入任何类型的对象并没有真正的区别,这些对象的状态稍后可能会改变,因为数组通常(在调用多个参数而不是数组的情况下)是编译器内部创建的一个新对象,您可以安全地使用,这当然是意想不到的行为。

为了调试,我经常使用可变参数输出到日志中。

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

private void debugPrint(Object... msg) {
for (Object item : msg) System.out.print(item);
System.out.println();
}

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

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

当我对我的代码工作满意时,我注释掉debugPrint()方法中的代码,这样日志就不会包含太多多余的和不需要的信息,但是我可以不注释对debugPrint()的各个调用。之后,如果我发现了一个错误,我只需取消对debugPrint()代码的注释,然后重新激活对debugPrint()的所有调用。

当然,我可以很容易地避免使用可变参数,而是执行以下操作:

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


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

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

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

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

此外,当参数的类型将发生变化时,则使用“Object…Test”将大大简化代码。

例如:

public int calculate(int...list) {
int sum = 0;
for (int item : list) {
sum += item;
}
return sum;
}

这里间接地将int类型的数组(list)作为参数传递,并在代码中作为数组处理。

为了更好地理解,请点击这个链接(它帮助我清楚地理解这个概念): http://www.javadb.com/using-varargs-in-java < / p > < p > p。S:甚至连我都不敢在不知道的情况下使用可变参数。但现在我已经习惯了。 正如俗话所说:“我们执着于已知,害怕未知”,所以尽可能多地使用它,你也会开始喜欢它:)

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


}

输出:

2

和是12

3.

和是21

在var - args的Java文档中,var args的用法非常清楚:

http://docs.oracle.com/javase/1.5.0/docs/guide/language/varargs.html

关于用法,它说:

"什么时候应该使用可变参数? 作为客户端,只要API提供它们,您就应该利用它们。在核心api中的重要用途包括反射、消息格式化和新的printf功能。 作为API设计人员,您应该谨慎使用它们,只有当好处真正引人注目时。 一般来说,你不应该重载一个varargs方法,否则程序员很难弄清楚调用了哪个重载。" < / p >