我们在用反射的方法执行main方法的时候,我们往调用类的main方法中的参数传入被调用类的类全名,然后根据该类名来执行main方法。
public class invokeClassMainMethod { public static void main(String[] args) throws Exception { Method startClassMainMethod= Class.forName(args[0]).getMethod("main", String[].class); startClassMainMethod.invoke(null, new String[]{"duancanmeng1","duancanmeng2","duancanmeng3"}); //备注 } }
这种方式表面上看是没有问题,但是由于java的历史遗留问题,所以会导致这里报参数异常, 而且是参数数量异常。
为什么会这样呢?我们分析一下原理:
java1.4是没有可变参数的,即Method.invoke(Obeject objecr ,Object obj[]{"xx","yy"});用数组传递多个参数 。
java1.5有了可变参数,即Method.invoke(Objet objecr,Object...args);用可变参数传递多个参数。
那是怎么导致的呢?
由于兼容性问题,在JDK1.4没有引入可变参数Object...类型,所以使用数组来表示,invoke函数接收到String数组后会进行拆分,得到两个String变量,但是没有main函数接受 两个String值,所以不行。
而且只要参数是new Object[]{“xxx”,”yyy”},javac 为了兼容1.4,只把它当作 jdk1.4 的语法进行理解,而不把它当作 jdk1.5 的语法解释,也就是说不能传递new String[]{};。
那解决方法:
1、mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});该方法还是会按1.4处理,会将参数打散,但没关系,里面就是对的参数new String[]{"xxx"}。
2、mainMethod.invoke(null,(Object)new String[]{"xxx"}); 不会打散,因为强转为Object了,编译器会认为这不是一个数组,此时是一个完整的参数。但注意他本质还是一个数组,作用仅仅是骗过编译器而已。
特别注意:只有main方法是这样,其他普通方法不会。