黑马程序员技术交流社区

标题: 学习动态代理,遇到一个纠结的问题,请大神指教 [打印本页]

作者: 傻瓜一点红    时间: 2013-9-17 10:51
标题: 学习动态代理,遇到一个纠结的问题,请大神指教
本帖最后由 杨增坤 于 2013-9-22 21:08 编辑

在学习动态代理时,遇到一个纠结的问题,用的是张孝祥老师的原代码(老师没测试),写的是动态代理获得的一个小型框架,但在用的时候却爆了异常,请大神指教
  1. import java.lang.reflect.InvocationHandler;
  2. import java.lang.reflect.Method;
  3. import java.lang.reflect.Proxy;
  4. import java.util.ArrayList;
  5. public class ProxyTest {
  6.         public static void main(String[] args) {//主函数
  7.                 ArrayList arr=new ArrayList();
  8.                 MyAdvice ma=new MyAdvice();//此处为加入的系统代码对象
  9.                 ArrayList al=(ArrayList)getProxy(arr,ma);<font color="#ff0000">/*此处爆类型异常,所爆异常为java.lang.ClassCastException,
  10.                 以致程序无法执行下去,如果换成Object al=getProxy(arr,ma);又无法调用add()方法,请大神指教
  11.                 */</font>
  12.                 al.add("455");               
  13.         }
  14.         private static Object getProxy(final Object target,final Advice advice){//获得动态代理
  15.                 Object proxy1=Proxy.newProxyInstance(
  16.                                 target.getClass().getClassLoader(),
  17.                                 target.getClass().getInterfaces(),
  18.                                 new InvocationHandler(){
  19.                         public Object invoke(Object proxy, Method method,
  20.                                         Object[] args) throws Throwable {
  21.                                 advice.beginTime();//系统代码调用
  22.                                 Object retVal=method.invoke(target, args);
  23.                                 advice.overTime();//系统代码调用
  24.                                 return retVal;
  25.                         }
  26.                 });
  27.                 return proxy1;
  28.         }
  29. }
复制代码
所爆异常全称为:Exception in thread "main" java.lang.ClassCastException: $Proxy0
        at selfstudy.ProxyTest.main(ProxyTest.java:19),所爆异常处在代码中已经指出,请大神指教

作者: 罗凯健    时间: 2013-9-17 11:23
很明显了,代理是面向接口的,你不能直接就用ArrayList来声明,换成Collection就可以了
作者: 刘劲松    时间: 2013-9-17 11:50
我把你的改了下,因为没有你的MyAdvice,自己写了个。
  1. public class Demo {

  2. /**
  3. * @param args
  4. */
  5. public static void main(String[] args) {
  6. final ArrayList arr=new ArrayList();
  7. Myadvice ma=new Myadvice();//此处为加入的系统代码对象
  8. List al=(List)getProxy(arr,ma);
  9. al.add("455");
  10. System.out.println(al);
  11. }
  12. private static Object getProxy(final Object target,final Advice advice){//获得动态代理
  13. Object proxy1=Proxy.newProxyInstance(
  14. target.getClass().getClassLoader(),
  15. target.getClass().getInterfaces(),
  16. new InvocationHandler(){
  17. @Override
  18. public Object invoke(Object proxy, Method method,
  19. Object[] args) throws Throwable {
  20. advice.beforeMethod(method);//系统代码调用
  21. Object retVal=method.invoke(target, args);
  22. advice.afterMethod(method);//系统代码调用
  23. return retVal;
  24. }



  25. });
  26. return proxy1;
  27. }

  28. }
复制代码
注意代理用的是他的接口,你看这句target.getClass().getInterfaces(),所以返回的代理对象应该List或者Collection之类的类型。


作者: 傻瓜一点红    时间: 2013-9-17 11:51
罗凯健 发表于 2013-9-17 11:23
很明显了,代理是面向接口的,你不能直接就用ArrayList来声明,换成Collection就可以了 ...

疏忽了细节,悲剧的搞了半天
作者: 傻瓜一点红    时间: 2013-9-17 11:56
刘劲松 发表于 2013-9-17 11:50
我把你的改了下,因为没有你的MyAdvice,自己写了个。注意代理用的是他的接口,你看这句target.getClass().g ...

谢谢,顺便说一下,好像List不行哦,似乎需要的是顶级接口

作者: 刘劲松    时间: 2013-9-17 12:15
傻瓜一点红 发表于 2013-9-17 11:56
谢谢,顺便说一下,好像List不行哦,似乎需要的是顶级接口

可以的。我运行了可以。只要这句里面有存入接口字节码就行 target.getClass().getInterfaces(), 这里的是Class[ ]数组。这时候你就应该去自己试一试。注意什么地方起作用,关键点在哪里。然后这个概念就了然了。现实中也很好理解IBM的代理商卖电脑,联想的代理商也得卖电脑。IBM和联想就是接口。只要你调用的方法是接口有的。其实相当于复写功能。

作者: 傻瓜一点红    时间: 2013-9-17 13:58
刘劲松 发表于 2013-9-17 12:15
可以的。我运行了可以。只要这句里面有存入接口字节码就行 target.getClass().getInterfaces(), 这里的是 ...

我试了,不行啊,用List会爆错啊,用List还是调用add方法,同样爆java.lang.ClassCastException,你那边能行?有点诡异
作者: 刘劲松    时间: 2013-9-17 14:31
傻瓜一点红 发表于 2013-9-17 13:58
我试了,不行啊,用List会爆错啊,用List还是调用add方法,同样爆java.lang.ClassCastException,你那边 ...



这个是运行结果,你对照下代码看看有没有不同的地方。是可以的,既然是实现List接口的,getinterfaces是有了接口字节码的,有了字节码invoke调用方法顺手的事情。

作者: 傻瓜一点红    时间: 2013-9-17 14:45
刘劲松 发表于 2013-9-17 14:31
这个是运行结果,你对照下代码看看有没有不同的地方。是可以的,既然是实现List接口的,getinterfaces ...

这下让我纠结了,我怎么运行都不行,试了ArrayList和LinkedList都不行,只要接口用List就爆错,以下图片是运行的结果,真不知道是怎么回事了

2013-09-17_144059.jpg (82.96 KB, 下载次数: 33)

2013-09-17_144059.jpg





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2