【日常记录-Java】可变长度参数
1. 问题描述
通过反射调用main方法,代码如下:
public class A {public static void main(String[] args){System.out.println("hello world!");}
}public class B {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {Class<?> clazz = Class.forName("A");Method method = clazz.getMethod("main", String[].class);method.invoke(null, args);}
}
以B作为入口类,当参数个数不为1时,报错为“Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments”。参数个数为1时,报错为“Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch”。
2. 问题分析
2.1 基础知识
在Java中,可变长度参数是一种允许方法接受任意数量参数(包括零个参数)的特性,该特性通过在参数类型后添加省略号(...)来声明。在方法内部,可变长度参数被视为一个数组,可以像处理数组一样处理该参数。相关要点如下:
- 声明方式:在参数类型后添加省略号(...);
- 位置要求:必须为方法参数列表的最后一个参数;
- 处理方式:方法内部可被视为一个数组;
- 调用方式:可以传递任意数量的参数,也可以传递一个数组作为参数。若传递一个数组,Java会自动将其视为可变长度参数;
2.2 分析
invoke函数的签名为public Object invoke(Object obj, Object... args);其第2个参数为可变长度参数,而示例代码中第2个参数为字符串数组。由2.1中的可变参数调用方式可知,Java会自动将其视为可变长度参数进行拆解;当字符串数组长度为1时,其被解析为String类型,与main方法的String[]类型不匹配,当字符串数据长度不为1时,其参数个数与main方法参数个数不匹配,从而导致反射调用报错。
3. 解决方案
为避免String[]被自动拆解,可在方法调用时进行类型转化。示例代码如下:
public class A {public static void main(String[] args){System.out.println("hello world!");}
}public class B {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {Class<?> clazz = Class.forName("A");Method method = clazz.getMethod("main", String[].class);method.invoke(null, (Object)args); // 类型转换为Object,避免自动拆解}
}