今天跟着张老师的视频学习了一天,在反射中提到用反射调用main方法的问题,其中有一点很不明白
Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);
mainMethod.invoke(null,(Object)new String[]{"111","222","333"});
这一句的(Object)转换很不理解,既然main方法要的参数是String []类型的,那么直接给他为什么不可以呢?为什么还要转换一下?这个问题我思考了很久,打算在论坛提问的,在书写这个问题的时候突然感悟了,所以在这里分享给大家。
首先,invoke方法的参数列表是这样的invoke(Object arg0, Object... arg1) throws ……,这就说明,arg1参数是可变参数,通常我们这样理解可变参数:给他传几个参数他就接受了几个参数,比如:
(1)invoke(null, "str1", "str2"); //可变参数接收2个String类型的参数(对)
(2)invoke(null,new String[]{"str1", "str2","str3"});//可变参数接收了1个String[]类型的参数(错)
而事实上并没有这么简单,可变参数会自动把数组分拆为多个参数,所以(2)是错误的,应该是接收了3个String类型的对象。这又是为什么呢?具体解释如下:
JDK在1.5版本之前,Java没有可变参数这种东西,多个不定数量的参数使用数组来传递,1.5版本之后才加入了可变参数这个功能,这样一来,以前的程序就会运行错误,出现不兼容问题。为了跟1.5以前的程序兼容,一个方法中接受可变参数的地方,如果传入数组,就会自动分解为多个参数。(2)传入的一个String数组,会自动分解为多个String传入,所以(2)可以等效于于;
(2等效)invoke(null,"str1","str2", "str3");//分拆为3个String对象。
现在,回到我们的问题,假设我们不用Object转换,那么我们讨论的那句就是这样写:
mainMethod.invoke(null, new String[]{"111","222","333"});
根据上面的分析,我们知道,这句话中的数组会自动分解,等效于
mainMethod.invoke(null, "111","222","333");
这样一来,传给main函数的参数为3个String字符串,而不是1个String数组(String[]),所以就出现了参数个数错误的异常。
解决方法有两种:
1.像题设一样,加入Object转换,把数组向上转换为Object的类型,就不会在赋值给可变参数时被分拆。
2.把String数组装入Object数组中,分拆一次之后剩下的就是String数组,刚好可以传给main函数使用。
mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}});
http://blog.csdn.net/joyep/article/details/7078865
在反射中,如果反射的对象调用的函数是一个数组类型的参数的话,如Method.invoke Constructor.newInstance() 它们里面的参数都是一个可变参数,但其在传递过程中会把它们当作一个个参数进行传递,而我们实际执行的函数的参数却是一个数组,所以会出现异常。所以我们在处理过程中。以二维数组的方式进行传递。它经过一次分解后仍然是一个一维数组,这样就可以了