Java 变长参数传参

问:下面程序段能正常编译吗?为什么?
class Demo {
    void func(String arg) {}
    void func(String... args) {}
    void func(String[] vars) {}
}

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

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

问:下面的程序段执行结果是什么?
public class Demo {
    static void func(Object... varargs) {
        System.out.println(varargs.length);
    }
    public static void main(String[] args) {
        //F1
        func(1024, new String[]{"1", "2", "3"}); //2
        //F2
        func(new String[]{"1", "2", "3"}); //3
        //F3
        func(1024, new Integer[]{1, 2, 3}); //2
        //F4
        func(1, 2, 3); //3
        //F5
        func(new Integer[]{1, 2}); //2
        //F6
        func(new int[]{1, 2, 3}); //1
        //F7
        func(1024, new int[]{1, 2, 3}); //2
        //F8
        func(null, new int[]{1, 2, 3}); //2
        //F9
        func(new Object[]{new String[]{"1", "2", "3"}}); //1
        //F10
        func((Object) (new String[]{"1", "2", "3"})); //1
    }
}

答:结果如每行调用后面的注释所示。

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

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

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

  4. F4 是最常见的正常调用了,没什么解释的。

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

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

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

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

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

你可能感兴趣的:(Java 变长参数传参)