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

提供给想学习云计算的同学,欢迎收听https://www.zhihu.com/lives/1046567982750281728

 

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值