第42条:慎用可变参数
Java 1.5发行版本中增加了可变参数方法。可变参数方法接受0个或者多个指定类型的参数。可变参数机制通过先创建一个数组,数组的大小为在调用位置所传递的参数数量,然后将参数值传到数组中,最后将数组传递给方法。
例如下面有个例子,返回多个参数的和:
static int sum(int... args) {
int sum=0;
for(int arg : args)
sum += arg;
return sum;
}
正如期望的那样,sum(1,2,3)的值为6,sum()的值为0。
有时候,我们需要至少一个参数,那么很容易想到在方法开始的时候做参数检查,下面是一个计算参数最小值:
static int min(int firstArg, int... remainingArgs) {
int min = firstArg;
for(int arg : remainingArgs)
if(arg < min)
min = arg;
return min;
}
但是,这是解决方案有几个问题。客户调用该方法时,如果没有传入参数进去,只有在运行的时候失败,还不是编译的时候失败。另一个问题是,这段代码不美观。
幸运的是,有一种更好的方法可以实现想要的这种效果。声明该方法有两个参数,一个是指定类型的正常参数,另一个是这种类型的varargs参数。这个方法弥补了上面的不足:
static int min(int firstArg, int... remainingArgs) {
int min = firstArg;
for (int arg : remainingArgs)
if (arg < min){
min = arg;
}
return min;
}
当你真的需要让一个方法带有不定数量的参数的时候,可变参数才会变得非常有效。它本来是为printf和反射机制设定的。
不必改造具有final数组参数的每个方法,只当确实是在数量不定的值上执行调用时才是用可变参数。
在重视性能的情况下,使用可变参数机制要特别小心。可变参数方法每次调用都会导致进行一次数组分配和初始化。如果只是凭经验确定,无法承受这一成本,但是又需要可变参数的灵活性。这时候,需要评估,假如某个方法95%会调用3个或更少的参数,那么就声明该方法的5个重载(和上一条一样,这几个重载的方法必须尽量保证方法的功能相同,返回值相同),每个重载方法带有0-3个参数,超过3个参数的时候,就会自动调用可变参数方法。
public void foo(){}
public void foo(int a1){}
public void foo(int a1, int a2){}
public void foo(int a1, int a2, int a3){}
public void foo(int a1, int a2, int a3, int... rest){}
简而言之,在定义参数数目不定的方法时,可变参数是一个很方便的方式,但是它们不应该被过度滥用,如果使用不当,会产生混乱的结果。