Effective Java(3rd)-Item53 谨慎使用可变参数

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


Effective Java(3rd)-Item53 谨慎使用可变参数_第1张图片
image.png

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


Effective Java(3rd)-Item53 谨慎使用可变参数_第2张图片
image.png

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


Effective Java(3rd)-Item53 谨慎使用可变参数_第3张图片
image.png

  从这个例子中可以看出,在需要参数数量可变的方法的情况下,varargs是有效的。Varargs是为与Varargs同时添加到平台上的printf和经过改造的核心反射设施( item65 )而设计的。printf和reflection都从varargs中受益匪浅。

  在性能关键的情况下使用varargs时要小心。每次调用varargs方法都会导致数组分配和初始化。如果你已经从经验上确定你负担不起这个成本,但是你需要varargs的灵活性,那么有一种模式可以让你鱼与熊掌兼得。假设您已经确定对方法的95%的调用具有三个或更少的参数。然后声明该方法的5次重载,每次重载0到3个普通参数,当参数数量超过3个时使用一个varargs方法:

  
Effective Java(3rd)-Item53 谨慎使用可变参数_第4张图片
image.png

  现在您知道,在所有参数数量超过3的调用中,只有5%的调用需要支付创建数组的成本。与大多数性能优化一样,这种技术通常不合适,但当它合适时,它是一个救星。
  EnumSet的静态工厂使用这种技术将创建枚举集的成本降到最低。这是适当的,因为enum集合为位字段提供具有性能竞争力的替换是至关重要的( item36 )。

  总之,当您需要定义具有可变数量参数的方法时,varargs是非常有用的。在varargs参数之前加上任何必需的参数,并注意使用varargs的性能后果。

本文写于2019.7.18,历时1天

你可能感兴趣的:(Effective Java(3rd)-Item53 谨慎使用可变参数)