黑马程序员技术交流社区
标题:
自己试验的反射中invoke解包问题
[打印本页]
作者:
Teemo_Mann
时间:
2014-4-24 16:03
标题:
自己试验的反射中invoke解包问题
看了张孝祥老师的 23_对接收数组参数的成员方法进行反射 这一节,关于在调用invoke时参数会自动解包的问题,
注:此篇文档是个人见解加个人实验结果,大家可以提出不同意见,共同进步
视频里只讲解了Main方法里的(String[] args)函数,我在想为什么会拆包?到底有哪些都会自动拆包呢,自己写的类,基础类型,还有一些Java提供的类都会吗?
带着这些疑问,首先看API
1.为什么会自动拆包
public
Object
invoke
(
Object
obj,
Object
... args) throws
IllegalAccessException
,
IllegalArgumentException
,
InvocationTargetException
对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
个别参数被自动解包,以便与基本形参相匹配,基本参数和引用参数都随需服从方法调用转换。
如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null。
如果底层方法所需的形参数为 0,则所提供的 args 数组长度可以为 0 或 null。
我们注意到个别参数被自动解包,再看上面invoke的参数(object obj,
Object...
args)注意这里是Object,其实也就不难理解为什么会自动解包了
因为Java1.5开始有可变参数的特性,当你放入一个String[] args的时候,那么编译器怎么知道你是要放入一个String[]对象,还是多个String对象呢.
所以编译器默认就把它进行解包,解成一个个String对象以便于基本形参相匹配了.
所以说我们在传入参数的时候可以用(Object)new String[]("123,"456","789")告诉编译器我只传一个Object,
另外一种就是骗过编译器new Object[](new String[]("123","456","789"))编译器拆了之后还是一个String[]数组.
2.哪些会自动拆包
我实验的结果是,除了基本数据类型数组,其他统统要拆包,废话不说上代码
import java.lang.reflect.Method;
import java.lang.Class;
import java.lang.Exception;
class MainReflect
{
public static void main(String[] args) throws Exception{
Method method1 = Class.forName("IntReflect").getMethod("intParams",int[].class);
Method method2 = Class.forName("StringReflect").getMethod("strParams",String[].class);
Method method3 = Class.forName("IntegerReflect").getMethod("integerParams",Integer[].class);
Method method4 = Class.forName("ObjectReflect").getMethod("objParams",NewObject[].class);
/*第一个invoke编译时系统是不会提示的,运行时也不会报错,正常输出123",<font color="#ff0000">所以基本数据类型的数组是不解包的</font>*/
method1.invoke(null,new int[]{1,2,3});
/*下面三个编译时
MainReflect.java:12: 警告:最后一个参数使用了不准确的变量类型的 varargs 方法的非
varargs 调用;对于 varargs 调用,应使用 java.lang.Object对于非 varargs 调用,
应使用 java.lang.Object[],这样也可以抑制此警告
其实看到这个提示我们就该明朗,我们用的是varargs调用,应该使用java.lang.Object,系统认不清
你的参数
我们再看编译时错误
Exception in thread "main" java.lang.IllegalArgumentException: wrong number of a
rguments
因为你只需要一个Integer对象[]对象,而你的方法拆成了三个Integer,不合法的参数异常.
*/
method2.invoke(null,new String[]{"111","222","333"});
method3.invoke(null,new Integer[]{10,20,30});
method4.invoke(null,new NewObject[]{new NewObject(),new NewObject()}); //<font color="#ff0000">自定义的类一样自动解包</font>
}
}
class IntReflect
{
public static void intParams(int[] args){
for(int i : args){
System.out.println(i);
}
}
}
class IntegerReflect
{
public static void integerParams(Integer[] args){
for(Integer i : args){
System.out.println(i);
}
}
}
class StringReflect
{
public static void strParams(String[] args){
for(String str : args){
System.out.println(str);
}
}
}
class ObjectReflect
{
public static void objParams(NewObject[] objs){
for(NewObject obj : objs){
obj.open();
}
}
}
class NewObject
{
public void open(){
System.out.println("hello");
}
}
复制代码
好了,以上是我的总结,欢迎大家讨论.
作者:
许庭洲
时间:
2014-4-24 21:04
值得学习ing!
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2