黑马程序员技术交流社区
标题:
创建动态类的实例对象为什么是Collection类型的?
[打印本页]
作者:
过犹不及
时间:
2014-7-3 17:18
标题:
创建动态类的实例对象为什么是Collection类型的?
就是这句话Collection proxy=(Collection)constructor.newInstance(new MyInvocationHandler());为什么是Collection。可能答案很简单,但我就是想不通,请各位大仙指点一下
作者:
李小然
时间:
2014-7-3 18:14
1.为什么是Collection?
回答这个问题,你要明白proxy是由constructor实例化出来的。
那么就要明白constructor是哪里来的。
Constructor constructor = clazz.getConstructor(InvocationHandler.class);
这话的意思是constructor是从clazz这个字节码文件中得到参数是InvocationHandler的构造函数。(动态代理的构造函数参数都是InvocationHandler)
就要明白clazz是什么。
Class clazz = getProxyClass(Collection.class.getClassLoader(),
Collection.class
);
这句话的意思是,创造一个动态代理字节码,需要实现
Collection.class这个字节码的接口。
你就明白了,原来问题是在这里。是这个字节码文件导致实例化出来对象是Collection的。
2.为什么要强转?使用(Collection)
这涉及到编译器的问题,他只可以解决编译阶段的问题。运行阶段的问题他是看不到的。
你在clazz中参数是Collection.class,你明白你在创造一个动态字节码文件,实现Collection接口。
但是编译器不明白,因为你可以随意更改这个字节码文件(保证是个接口),编译器不会那么智能的判断出实例化出来的是什么东西。
所以返回的是
一个Object对象
,他可以接受任意你选择的字节码接口文件。
所以如果你不强转,
一个父类引用是不可以指向子类的
。会出现错误。
3.即便你这样写了,其实真正意义上来讲,这个动态代理对象没有真正实现Collection的所有功能。
他只有形,而没有魂。类似于写一个网页文件你只做了前台,后台的功能还没添加。
这就需要了解InvocationHandler这个接口的作用。
这个接口中只需要重写一个
[size=-1]
Object
invoke
(
Object
proxy,
Method
method,
Object
[] args)
这个方法。需要实际指定的是proxy这个对象。
你将Object proxy = new ArrayList();
Object retVal = method.invoke(proxy, args);
return retVal;
指定之后,这个动态代理就会有血有肉。
事实上,
其实整个过程就是做了一个Collection colection = new ArrayList();这样一个简单的操作。
如果哪里没有说明白,你哪里不明白,还可以继续留言,我继续给你回复。
{:3_57:}
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2