MENU

Java 杂记(七)坑:反射与可变参数类型

June 25, 2018 • Code

前言:当程序中出现可变参数时,需要特别注意可能存在的坑。

主要内容

栗子

下述栗子为反射时可变参数可能出现的情况。

public class Test {
    
    public void func(String[] args) {
        System.out.println((args == null) ? "null" : args.length);
    }
    public static void main(String[] args) throws Exception {
        Test obj = new Test();
        Method m = obj.getClass().getMethod("func", String[].class);
        m.invoke(obj, new String[1]);  //1
        m.invoke(obj, new Object[]{new String[] {"a", "b"}}); //2
        m.invoke(obj, (Object) new String[] {"a", "b"}); //3
        m.invoke(obj, new String[] {"a"});  //4
        m.invoke(obj, new String[] {"a", "b"}); //5
        m.invoke(obj, new String[2]);  //6
    }
}

结果如下:

分析

下述的自动装箱与拆箱与 Java 中包装类与基本数据类型涉及的语法糖不同,只因过程相同,故借此描述。

首先需要明确:invoke 方法参数列表中最后一个为可变参数,所以只有一个参数传入时会自动拆解

1. new String[1]

只传入一个参数 new String[1]自动拆解后发现里面只有一个 null,故传给 args 的值为 null。

2. new Object[]{new String[] {"a", "b"}}

同上一个,自动解析后发现里面为 new String[] {"a", "b"},传入 args,输出个数为 2。

3. (Object) new String[] {"a", "b"})

强转成 Object 可看作将 String[] 数组包装成一个对象,因此传给 args 时会自动拆箱,args 得到正常 String 数组。

4. new String[] {"a"}

相比上一个栗子,没有强转成 Object,但因为也是只有一个参数(数组),所以也会自动拆解,得到字符串 a,但是 args 类型为 String 数组,类型不符合,出错。

5. new String[] {"a", "b"}6. new String[2]

原理同上,不同在于拆解后会得到两个参数(a 和 b 或 null 和 null),此时并不会自动装箱,因此会报错,因为并不存在两个形参的方法签名

小结

总的来说,就是单个参数 + 可变参数 = 可能会自动拆解,对拆解后的结果需要格外小心对待。

参考

Last Modified: July 5, 2018
Archives QR Code
QR Code for this page
Tipping QR Code
Leave a Comment