问:下面程序段能正常编译吗?为什么?
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
}
}
答:结果如每行调用后面的注释所示。
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。