当前位置: 首页 > 科技观察

你真的了解Java中的可变参数吗?

时间:2023-03-13 18:56:26 科技观察

本文转载自微信公众号《Java极客技术》,作者鸭血范唐。转载本文请联系Java极客技术公众号。我们都知道Java支持可变参数的形式化定义方式。这个语法糖在某些时候可以简化我们的代码,但是你真的知道可变参数是如何实现的以及其他细节吗?今天阿粉就带你一探究竟。变参方法的定义首先看代码中是如何定义变参方法的,如下:publicstaticvoidmethod1(Integerid,String...names){System.out.println("id:"+id+"names:"+names.length);}通过上面的例子我们可以看出,在定义一个方法的时候,在最后一个形参类型后面加上三个点...,表示这个形参可以接受多个参数值的同一个类型,多个参数值以数组形式传入。这里需要注意几点:可变参数只能作为函数的最后一个参数,它之前可能有也可能没有其他参数;由于可变参数必须是最后一个参数,因此一个函数最多只能有一个可变参数;Java的可变参数会被编译器转化为数组;上面提到的可变参数的形式会被编译成一个数组,那么问题来了,我能不能像下面这样写两个方法呢??publicstaticvoidmethod1(Integerid,String...names){System.out.println("id:"+id+"names:"+names.length);}publicstaticvoidmethod1(Integerid,String[]names){System.out.println("id:"+id+"names:"+names.length);}在一个类中定义一个同名的可变参数方法和一个包含数组的方法。写完后发现IDEA提示我们这种写法无法编译。从这里我们可以知道,可变参数编译成字节码后,会以数组的形式出现在方法签名中,导致两个方法的签名相同。如果它们同时出现,则无法编译。可变参数方法的调用可变参数方法的调用与其他方法的调用没有区别。这里要说明的是,除了通过可变参数调用外,我们还可以通过传入数组的形式来调用,如下所示:publicstaticvoidmain(String[]args){//直接传参method1(1"ziyou","java极客技术");//以数组形式传递参数String[]array=newString[]{"ziyou","Java极客技术","fdf"};method1(2,array);//不传可变参数method1(3);}通过可变参数和数组的形式,这两种调用形式的本质与上面相同;另外,可变参数的个数也可以为0。可变参数方法的重载想象一下,如果我们定义下面两个方法,当我们定义并使用publicstaticvoidmethod2(String...names){System.out.println时会发生什么("111111");}publicstaticvoidmethod2(Stringvalue1,Stringvalue2){System.out.println("22222");}第一种是只有一个可变参数参数的方法;第二个是String类型的固定参数,第二个参数是改变参数的可变方法。首先定义的时候完全没有问题,IDEA没有任何错误提示,编译也没有问题。那你什么时候用呢?例如,下面的写法会输出什么?publicstaticvoidmain(String[]args){method2("javageektechnology","ziyou");}在看输出结果之前,我们可以看到main函数中的调用,其实这两个重载函数就可以满足,并且编译正确,那么程序会输出什么呢?通过实际运行结果可以看出,输出结果为22222,说明方法method2(Stringvalue1,Stringvalue2)在运行,那么问题出在哪里呢?说明当有重载的方法有可变参数的方法时,固定参数的方法会先执行。相信大家应该都没有关注过。说到这里,小明可能会问,如果我们第二个方法中的value2也是一个可变参数呢?在这种情况下会发生什么?为此,让我们看看下面的形式会发生什么。publicstaticvoidmethod2(String...names){System.out.println("111111");}publicstaticvoidmethod2(Stringvalue1,Stringvalue2){System.out.println("22222");}publicstaticvoidmethod2(Stringvalue1,String...value2){System.out.println("33333");}第一次定义时,IDEA没有任何错误提示,说明编译没有问题。打电话的时候怎么办?可以看到此时IDEA已经提示我们匹配多个方法无法编译出合适的方法,主要是第一种和第三种写法,匹配的方法有多个可变参数,在日常开发中要注意这个问题。Object可变参数看到这里,小明会问,我可不可以基于Object创建一个可变参数方法,让这个方法可以接受所有类型的参数?像这样:publicstaticvoidmethod3(Object...objects){System.out.println("objectssize"+objects.length);}首先要说的是这样的定义当然没有问题,但是可读性会更糟的是,调用者不知道该怎么做传入了什么类型?这样的代码如果真的写多了,维护起来估计害人害己。