今天跟着张老师的视频学习了一天,在反射中提到用反射调用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"}});
以上是我对于反射以及可变参数的浅薄理解,初学讨论,如有不妥之处,欢迎指正,谢谢大家。