Java 变长参数,8

https://mp.weixin.qq.com/s/yKCUlvaL9GwgpvSjBtvihQ

https://mp.weixin.qq.com/s?__biz=MzI3ODc3NzQ4NQ==&mid=2247483751&idx=1&sn=be19baaeb35b1b26f40ea3197fa77fa7&chksm=eb509a85dc27139306b057b67c2d17ec39820247fd8e4c2071654af6d913ab732dbbae5dea4e&scene=21#wechat_redirect

是什么:

  在 Java 5 中提供了变长参数,允许在调用方法时传入不定长度的参数。变长参数是 Java 的一个语法糖,本质上还是基于数组的实现:

public class test{
    public static void test(String...args){
    //本质上还是基于数组的实现:
        for(String arg : args) {//当作数组用foreach遍历
            System.out.println(arg);
        }
    }

    public static void main(String[] args) {
        test("aa", "bb", "cc");
    }
}

使用规则:

  • 一个方法只可以有一个变长参数
  • 边长参数的位置必须是最后一个
问:找出下面程序存在的问题并只允许修改调用相关代码将其修复好?

    public class Demo {

        public void print(String str, Integer... args) {}

        public void print(String str, String... args) {}

    }


    //调用

    Demo demo = new Demo();

    demo.print("hello");

    demo.print("hello", null);


答:上面代码直接编译报错,因为调用处对于两个方法都能匹配,编译器不知道选哪个,所以报错了,故别让 null 值和空值威胁到变长方法调用,对于上面调用部分来说修改如下即可运行:

    Demo demo = new Demo();

    String[] strs = null;

    demo.print("hello", strs);
问:分别说说下面程序注释行有问题吗,为什么?

    class Base {

        void print(String... args) {

            System.out.println("Base print.");

        }

    }


    class Sub extends Base {

        @Override

        void print(String[] args) {

            System.out.println("Sub print.");

        }

    }


    Base base = new Sub();

    base.print("hello");    //1


    Sub sub = new Sub();

    sub.print("hello");    //2


答:注释 1 能编译通过且打印为 Sub print.,因为 base引用变量把子类对象 sub 做了向上转型,形参列表是由父类决定的,当然能通过。****编译看左边,运行看右边。【当父类引用变量指向子类对象的时候,会将子类对象向上转型】

注释 2 编译报错为传递的参数 String 类型与方法需要的 String[] 类型不匹配,因为这时编译器看到子类覆写了父类的 print 方法,所以会使用子类重新定义的 print 方法,尽管参数列表不匹配也不会再去父类匹配(
因为找到了就不再找了),故有了类型不匹配的编译错误。---------【针对子类重写了父类方法,用子类变量指向子类对象时调用的情况,先确定方法,再匹配参数】
****先确定该引用变量指向哪一个对象,其次看调用方法,之后再匹配参数列表,看是否回编译通过。
这段代码要特别注意上面子类重写父类的 print 是成立的,因为父类 Base 的 print 方法的 args 变长参数在编译成字节码后的表现是一个 String 数组类型的形参,而子类重写时正是 String[] 类型,
所以自然就是重写而不是重载,故加上 @Override 也没有问题的。

使用场景:在不确定方法需要处理的对象的数量时可以使用可变长参数,会使得方法调用更简单