Java 变长参数相关的坑

下面程序段能正常编译吗?为什么?

class Demo {
    void func(String arg) {}
    void func(String... args) {}
    void func(String[] vars) {}
}

上面的类无法编译,会提示方法重复冲突。

输入图片说明

因为 java 方法的变长参数只是一种语法糖,其本质上还是将变长的实际参数 args 包装成了一个数组,所以 String[] args 与 String... vars 会被当作是相同签名的方法,故在源码级别是不能同时存在的,所以无法编译通过。

下面的程序段执行结果是什么?

    static void func(Object... varargs) {
        System.out.println(varargs.length);
    }

    public static void main(String[] args) {

        // F1
        func(1024, new String[]{"1", "2", "3"});

        // F2
        func(new String[]{"1", "2", "3"});

        // F3
        func(1024, new Integer[]{1, 2, 3});

        // F4
        func(1, 2, 3);

        // F5
        func(new Integer[]{1, 2, 3});

        // F6
        func(new int[]{1, 2, 3});

        // F7
        func(1024, new int[]{1, 2, 3});

        // F8
        func(null, new int[]{1, 2, 3});

        // F9
        func(new Object[]{new String[]{"1","2","3"}});

        // F10
        func((Object) (new String[]{"1", "2", "3"}));

    }

输入图片说明

F1在编译时由于明确传入了两个实参,两个实参都是 Object 类型,所以能被正常识别长度是 2。

F2在编译时由于只传递了一个 String 数组,而 String 是对象类型的,所以在传递时被拆分成了数组长度个参数,所以长度是 3。

F3在编译时原理完全同 F1。

F4是最常见的正常调用了,没啥解释的。

F5在编译时原理完全同F2。

F6在编译时由于 int[] 没有办法直接转型成 Object[] ,因为基本类型与 Object 是无法匹配的,所以 int[] 被当作一个单纯的数组对象包装成类似 Object[]{int[]} 形式,所以长度是 1。而 Integer[] 本身就是 Object[],所以才有了 F2、F5 的现象。

F7、F8 在编译时同理 F1、F3。

F9 在编译时实质就是 Object[] 数组的一个元素,只不过这个元素又是一个 String[] 数组而已,所以打印为 1。

F10 在编译时虽然是 String[] 数组,但是在传递给变长参数时被强转成了 Object 类型,所以整个 String[] 数组被当成了一个整体,所以打印长度为 1。

猜你喜欢

转载自my.oschina.net/hensemlee/blog/1803068