Java中的可变参数
Java在1.5之后允许方法使用可变参数,可变参数的好处在于:它允许传递0个或者多个参数。比如原来有一段代码如下:
public class Test { public static void main(String[] args) { test(); test(new String[]{"a"}); test(new String[]{"a", "b"}); } private static void test() { System.out.println(“[]”); } private static void test(String[] args) { System.out.println(Arrays.toString(args)); } }
使用可变参数之后的代码如下:
public class Test { public static void main(String[] args) { test(); test(new String[]{"a"}); test(new String[]{"a", "b"}); } private static void test(String... args) { System.out.println(Arrays.toString(args)); } }
可见,可变参数的功能更加强大,语意包含的范围更广。
我们知道,在Java中,除了8种基本类型之外一切都是类。那么可变参数到底是个什么类呢?来,用代码验证下!
public class Test { public static void main(String[] args) { whatClass(); whatClass1(); } private static void whatClass(String... args) { System.out.println(args.getClass()); System.out.println(new String[]{}.getClass()); } private static void whatClass1(int... args) { System.out.println(args.getClass()); System.out.println(new int[]{}.getClass()); } }
上面代码的运行结果是:
class [Ljava.lang.String; class [Ljava.lang.String; class [I class [I
可见,可变参数在运行时还是会被JVM转变成一个数组,所以当我们使用可变参数的时候,实际上又一个隐含的过程,就是创建一个数组并且赋初值。当我们对性能敏感时,这一特性可能会坑了我们,为何这样说?看下面的代码:
public class Test { public static void main(String[] args) { long start = System.currentTimeMillis(); int sum = 0; for (int i = 0; i < 10000; i++) { sum += test1(1); } long end = System.currentTimeMillis(); System.out.println(end - start); start = System.currentTimeMillis(); sum = 0; for (int i = 0; i < 1000000; i++) { sum += test2(1); } end = System.currentTimeMillis(); System.out.println(end - start); } private static int test2(int... args) { return args[0]; } private static int test1(int first) { return first; } }
test2的时间大于test1的时间,这种差别随着循环次数的增大越来越明显。这种性能的参数就是可变参数的“功劳”。因此,我们总见到这样的方法重载:
public void fun(int val1){} public void fun(int val1,int val2){} public void fun(int val1,int val2,int val3){} public void fun(int val1,int val2,int val3,int... args){}
当fun方法的大多数调用都是有1-3个参数值的时候,使用上面的方法比仅有一个可变参数的方法性能要好的多,因为很少能用到可变参数的方法。这种例子最常见的就是JDK中的EnumSet类型的of()方法。看过的小伙伴可能对of(E first, E... rest)方法有些疑问,这个方法和of(E first,E second)等方法是“冲突”的啊?
实际上,Java是很聪明的。Java语法规定,可变参数必须在所有参数的最后声明,而且Java会首先寻找满足条件的不包含可变参数的方法,如果没找到,再使用包含可变参数的方法,看下面的例子:
public class Test { public static void main(String[] args) { fun(1); fun(1, 2); fun(1, 2, 3); fun(1, 2, 3, 4); fun(1, 2, 3, 4, 5); } private static void fun(int val1) { System.out.println("fun(int val1)"); } private static void fun(int val1, int val2) { System.out.println("fun(int val1, int val2)"); } private static void fun(int val1, int val2, int val3) { System.out.println("fun(int val1,int val2,int val3)"); } private static void fun(int val1, int... args) { System.out.println("fun(int val1, int val2, int val3, int... args)"); } }
笔者开设了一个知乎live,详细的介绍的JAVA从入门到精通该如何学,学什么?
提供给想深入学习和提高JAVA能力的同学,欢迎收听https://www.zhihu.com/lives/932192204248682496
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: java 可变参数方法不支持多个可变参数以及多种类型的替代方法
- 下一篇: Java可变参数