Effective Java 读书笔记——42:慎用可变参数
来源:互联网 发布:山东理工大学网络教育 编辑:程序博客网 时间:2024/05/18 11:46
从Java 1.5开始就增加了可变参数(varargs)方法,又称作variable arity method。可变参数方法接受0个或多个指定类型的参数。它的机制是先创建一个数组,数组的大小为调用位置所传递的参数数量,然后将值传到数组中,最后将数组传递到方法。
例如下面有个例子,返回多个参数的和:
// Simple use of varargs - Page 197 static int sum(int... args) { int sum = 0; for (int arg : args) sum += arg; return sum; }
常常,我们需要至少一个参数,那么很容易想到在方法开始的时候做参数检查,下面是一个计算参数最小值的例子:
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; }
以上是在方法开始的时候检查参数长度是否为0。但是,这是解决方案有两个不足:1.如果没有传入参数,只有在运行的时候失败,还不是编译的时候失败;2.代码不美观,除了需要在最开始检查有效性之外,在这个案例中,比较参数的大小的时候,只能从数组第二个开始比较(这也是我经常遇到的问题),代码不够简洁美观。
很巧的是,利用可变参数的语法,正好有一种巧妙的方法可以解决这个问题:声明该方法有两个参数,一个是指定类型的正常参数,另一个是这种类型的varargs参数。这个方法弥补了上面的不足(不需要再检查参数的数量了,因为至少要传递一个参数,否则不能通过编译):
static int min(int firstArg, int... remainingArgs) { int min = firstArg; for (int arg : remainingArgs) if (arg < min) min = arg; return min; }事实上,当你真的需要让一个方法带有不定数量的参数的时候,可变参数才会变得非常有效。它本来是为printf和反射机制设定的。
接下来让我们一起看看一个有趣的例子:
List<String> homophones = Arrays.asList("to", "too", "two");System.out.println(homophones);int[] digits = { 1, 2, 3, 4, 5 };System.out.println(Arrays.asList(digits));输出结果是:
[to, too, two][[I@15db9742]
在以上的这个例子中,System.out.println调用的是toString,而List是从Object继承了它们的toString实现。如果使用asList方法来初始化int数组,它会忠实的将int数组包装到List<int[]>实例中,打印这个列表会导致到列表中调用toString,toString的是int[],打印的是数组地址,得到我们并不想看到的结果。
List<int[]> list=Arrays.asList(digits);我将代码稍作修改,更能说明这个问题:
List<String> homophones = Arrays.asList("to", "too", "two");System.out.println(homophones);int[] digits = { 1, 2, 3, 4, 5 };List<int[]> list=Arrays.asList(digits);System.out.println(list);String[] strs={"to", "too", "two"};System.out.println(strs);System.out.println(digits);输出结果是:
[to, too, two][[I@15db9742][Ljava.lang.String;@6d06d69c[I@15db9742
使用Arrays.toString方法就可以避免这个问题。
另外,需要注意的是,在重视性能的情况下,使用可变参数机制要特别小心。可变参数方法每次调用都会导致进行一次数组分配和初始化。如果只是凭经验确定,无法承受这一成本,但是又需要可变参数的灵活性。这时候,需要评估,假如某个方法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){}像大多数的性能优化方法一样,这种方式看起来很不恰当,但是用到的时候会有很大帮助。
总之,和其他规则一样,尽管可变参数是一个很方便的方式,但是它们不应该被过度滥用。除非有必要,尽量不要使用这种方法。
0 0
- Effective Java 读书笔记——42:慎用可变参数
- Effective Java慎用可变参数
- Effective Java 读书笔记——71:慎用延迟初始化
- Effective Java 读书笔记——41:慎用重载
- (42):慎用可变参数
- 第42条:慎用可变参数
- Effective Java 读书笔记——38:检查参数的有效性
- Java—可变参数
- Java—可变参数
- Effective Java 读书笔记——66:同步访问共享的可变数据
- 《Effective java》—–读书笔记
- 《Effective java》—–读书笔记
- Effective Java慎用重载
- Java——可变参数
- 2015062807 - EffactiveJava笔记 - 第42条 慎用可变参数
- 《Effective java》读书笔记4——泛型
- 《Effective java》读书笔记5——枚举
- 《Effective java》读书笔记7——异常
- Java读取excel数据并用Arraylist存储
- go语言快速入门:自动化测试(17)
- Leetcode Graph Valid Tree
- cocos2dX中c++和lua的交互-1
- Route Between Two Nodes in Graph
- Effective Java 读书笔记——42:慎用可变参数
- ceres solver使用
- 技术人成长百科指南:给你一束光,路在你脚下
- JAVA基础面试题
- 现代微积分何时传入中国?
- LinuxLog分析常用组合命令
- 安卓基础面试题
- 安卓高级面试题
- Labwindows 同时画多条曲线