您的位置 首页 java

你对Java中可变参数的方法了解多少?

快来看看,你对Java中可变参数的方法了解多少?

J2SE 1.5 提供了Varargs机制(可变参数),允许直接定义能和多个实参相匹配的 形参

之前都是用“数组包裹实参”的办法解决实参个数可变的情况。

从而,可以用一种更简单的方式,来传递个数可变的实参。更大的提高了方法的 重!用!性!

Varargs 的含义

【大体说来,“ Varargs ”是“variable number of arguments”的意思。有时候也被简单的称为“variable arguments” 】

方法声明的语法:

修饰符 返回类型 方法名(普通类型的形参,可变参数类型的形参){

}

方法声明的示例:

public static void method(String str,int…args){

}

注意哦:形参的“类型”与“参数名”之间加上三个连续的“.”(即“…”,英文里的句中省略号),就可以让它和不确定个实参相匹配

方法使用说明:

1 、方法中,对可变参数的处理 为数组类型, 我们通过看 源码 得知

编译器会在背地里把这最后一个形参转化为一个数组形参,并在编译出的class文件里作上一个记号,表明这是个实参个数可变的方法。

所以:在方法体中,我们可以把args当做一个数组来使用,数组童鞋有的,我也都有,比如length属性,比如也可以通过循环遍历数组的每个元素

示例:

public static void method(String str, int …args){

int sum =0;

for ( int i=0;i<args.length;i++){

sum+=args[i];

}

System. out .println(str+”的总成绩是:”+sum);

}

2 、调用带有可变参数的方法时,可变参数的实参值可以为0个,可以为多个,也可以为数组哦

如调用 public static void method(String str, int …args){} 时

以下语法皆可以:

method(“john”);

method(“john”,1,2);

method(“john”,1,2,3);

method(“john”,new int[]{1,2,3});

3 、可变参数要放在形参列表的最后

好吧,我们通过反推法,假如可以放在前面,比如

public static void method( int …args,int a){}

试问,如何得知 调用该方法 时,method(1,2,3),到底是1 2 3为可变参数的实参值,还是什么??

所以容易混淆,JVM是不允许发生这!种!现!象的!

4 、形参列表中至多允许一个可变参数 ,道理同3

示例:

public static void method(String a,int…b,int…c){} ×

public static void method(String a,int…b,String…c){} ×

看到这里,是不是对可变参数的方法,有了一定的了解了啊,那就试着做一套题目吧。

题目一:可变参数+多态

public class TestSub {

public static void main(String[] args) {

Base base=new Sub();// ①

base.add(1,2,3); // ②

}

}

class Base {

public void add (int a, int… arr ){

System.out.println(“base”);

}

}

class Sub extends Base{

public void add(int a, int[] arr ){

System.out.println(“sub_1”);

}

public void add(int a , int b, int c ){

System.out.println(“sub_2”);

}

}

试问打印结果?

80%的小伙伴会认为是 sub_2吧,哈哈,恭喜你!!!

,猜!错!了!

正确答案:sub_1

原因是:执行②时,步骤为 先检测父类Base中有无定义满足该实参列表的方法add,如果没有,则编译报错。如果有则继续检测子类Sub中有无重写,而因为可变参数会被解析成数组类型(通过反编译源码得知),所以认为 add(int a,int[] arr)为其重写 的方法!!!

题目二:可变参数+ 泛型

我们都知道的,泛型和可变参数都是J2SE1.5出现的新特性,如果这两个合在一起,会是神马效果呢?好期待哦

public static void method(T…args){ }

问题:是否编译通过?

正确答案:不可以。( 你猜对啦吗?)

原因是:J2SE 1.5中的泛型机制的一个内在约束——不能拿用标识符来代表的类型来创建这一类型的实例。在出现支持没有了这个约束的Java版本之前,对于这个问题,基本没有太好的解决办法。

不过,传统的“用数组包裹”的做法,并不受这个约束的限制。

比如,可以写成:

public static void method(T[] args){ }

题目三:可变参数+自动装拆箱

如果可变参数 遇上 自动装拆箱呢?

public class OverloadingSampleC {

public static void main(String[] args) {

testOverloading(1, 2);

testOverloading(new Integer(1), new Integer(2));

}

private static void testOverloading(int… args) {

}

private static void testOverloading(Integer… args) {

}

}

正确答案: 两句调用都会报编译错误的哦

原因是:容易出现混淆喽,Java是不允许出现这种情况的,所以直接报错啦

题目四:何必为难编译器

public class OverloadingSampleB {

public static void main(String[] args) {

testOverloading(1, 2, 3);//①

}

private static void testOverloading(Object… args) {

System.out.println(“周芷若 “);

}

private static void testOverloading(Object o, Object… args) {

System.out.println(“赵敏 “);

}

}

试问调用后的打印结果?

是不是很纠结?哈哈

你都这样纠结,更何况编译器了,所以…

正确答案:编!译!报!错!

原因是:这就不用问原因了吧,

对这种现象编译器很为难的哦

题目五:最后一题喽,看看调用完的打印结果

public class OverloadingSampleA {

public static void main(String[] args) {

testOverloading(1);//①

testOverloading(1, 2);//②

testOverloading(1, 2, 3);//③

}

private static void testOverloading(int i) {

System.out.print(“A\t”);

}

private static void testOverloading(int i, int j) {

System.out.print(“B\t”);

}

private static void testOverloading(int i, int… more) {

System.out.print(“C\t”);

}

}

说实话,你是不是稍微有些

呢,嘻嘻,好吧公布答案啦

正确答案:A B C

原因是: 实参个数固定的版本优先

总之哦,和J2SE1.5前 “用数组包裹”的做法相比,真正的实参个数可变的方法,在调用时传递参数的操作更为简单,含义也更为清楚。不过,这一机制也有它自身的局限,并不是一个完美无缺的解决方案。

文章来源:智云一二三科技

文章标题:你对Java中可变参数的方法了解多少?

文章地址:https://www.zhihuclub.com/199872.shtml

关于作者: 智云科技

热门文章

网站地图