美文网首页
ITEM 53: 谨慎的使用可变参数

ITEM 53: 谨慎的使用可变参数

作者: rabbittttt | 来源:发表于2019-12-13 19:45 被阅读0次

ITEM 53: USE VARARGS JUDICIOUSLY
  可变参数方法的正式名称是变量特性方法[JLS, 8.4.1],它接受指定类型的零个或多个参数。首先创建一个数组,其大小是在调用站点传递的参数的数量,然后将参数值放入数组,最后将数组传递给方法。
  例如,这里有一个可变参数方法,它接受一系列 int 参数并返回它们的和。如您所料,sum(1,2,3)的值为6, sum()的值为0:

// Simple use of varargs
static int sum(int... args) { 
  int sum = 0;
  for (int arg : args)
    sum += arg; 
  return sum;
}

  有时,编写一个方法需要一个或多个某种类型的参数,而不是零个或多个参数。例如,假设您想要编写一个函数来计算其参数的最小值。如果客户机没有传递任何参数,则此函数没有得到很好的定义。你可以在运行时检查数组长度:

// The WRONG way to use varargs to pass one or more arguments!
static int min(int... args) {
  if (args.length == 0)
    throw new IllegalArgumentException("Too few arguments");
  int min = args[0];
  for (int i = 1; i < args.length; i++)
    if (args[i] < min) 
      min = args[i];
  return min; 
}

  这个解决方案有几个问题。最严重的情况是,如果客户端不带参数调用此方法,则在运行时而不是编译时失败。另一个问题是它很丑。必须包含对args的显式有效性检查,并且不能使用for-each循环,除非初始化 min = Integer.MAX_VALUE,这也很难看。
  幸运的是,有一个更好的方法来达到预期的效果。声明获取两个参数的方法,一个是指定类型的普通参数,另一个是该类型的可变参数。这个解决方案弥补了前一个的所有不足:

// The right way to use varargs to pass one or more arguments
static int min(int firstArg, int... remainingArgs) {
  int min = firstArg;
  for (int arg : remainingArgs)
    if (arg < min) 
      min = arg;
  return min; 
}

从这个例子中可  以看出,在需要具有可变数量参数的方法的情况下,可变参数方法是有效的。Varargs 是为与 Varargs 同时添加到平台上的 printf 和经过改造的核心反射设施(item 65)而设计的。printf 和 reflection 都从 varargs 中受益匪浅。
  在性能关键的情况下使用 varargs 时要小心。每次调用 varargs 方法都会导致数组分配和初始化。如果你已经从经验上确定你负担不起这个成本,但是你需要 varargs 的灵活性,有一种模式可以让你鱼与熊掌兼得。假设您已经确定95%的方法调用有三个或更少的参数。然后声明该方法的5次重载,每次重载0到3个普通参数,当参数数量超过3个时使用一个 varargs 方法:

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

  现在您知道了,在所有参数数量超过3的调用中,您只需要支付5%的数组创建成本。与大多数性能优化一样,这种技术通常是不合适的,但是当它合适的时候,它是一个救星。EnumSet 的静态工厂使用这种技术将创建 enum 集的成本降到最低。这是适当的,因为关键是 enum 集合为位字段提供具有性能竞争力的替换(item 36)。
  总之,当您需要用可变数量的参数定义方法时,varargs 是非常有用的。在 varargs 参数之前加上任何必需的参数,并注意使用 varargs 的性能后果。

相关文章

网友评论

      本文标题:ITEM 53: 谨慎的使用可变参数

      本文链接:https://www.haomeiwen.com/subject/vblqnctx.html