当前位置: 代码迷 >> J2EE >> 100分赏格 java的JDK的动态代理的一个疑惑
  详细解决方案

100分赏格 java的JDK的动态代理的一个疑惑

热度:147   发布时间:2016-04-17 23:43:31.0
100分悬赏 java的JDK的动态代理的一个疑惑
我刚刚在看JAVA的JDK的代理 然后自己做了个例子测试
 
public interface Subject {
 int request();
 void hello();
 }
 

public class RealSubject implements Subject{
     public RealSubject(){};
 public int request() {
   System.out.println("realsubject");
   return 1;
 }
 public void hello() {
   System.out.println("hello");
 }
 }
 
public class ProxySubject implements InvocationHandler {
 private Object obj;
 public ProxySubject(Object  obj){
   this.obj=obj;
 }
 public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable {
   System.out.println("增强前");
     Object m=method.invoke(obj, args);
         System.out.println("增强后");
         System.out.println(m);
         return m;   
//如果红色的部分改成return null 那么执行有返回值的方法就会报空指针异常  为啥呢    如果方法没有返回值 可以return null  如果有返回值 必须return  m; }
 }
 

public class Test {
 public static void main(String[] args) {
 ProxySubject  proxy=new ProxySubject(new RealSubject());
 Subject sub=(Subject) Proxy.newProxyInstance(RealSubject.class.getClassLoader(),RealSubject.class.getInterfaces(), proxy);
 sub.request();
 sub.hello();
 }
 }
 
如果红色的部分改成return null 那么执行有返回值的方法就会报空指针异常  为啥呢    如果方法没有返回值 可以return null  如果有返回值 必须return  m;否则报空指针异常
 
------解决方案--------------------
int request();
这个肯定不能是null,换成Object试试
------解决方案--------------------
本帖最后由 fangmingshijie 于 2014-09-02 17:25:18 编辑
这个没有什么异议吧,看invoke的return的api说明
the value to return from the method invocation on the proxy instance. If the declared return type of the interface method is a primitive type, then the value returned by this method must be an instance of the corresponding primitive wrapper class; otherwise, it must be a type assignable to the declared return type. If the value returned by this method is null and the interface method's return type is primitive, then a NullPointerException will be thrown by the method invocation on the proxy instance. If the value returned by this method is otherwise not compatible with the interface method's declared return type as described above, a ClassCastException will be thrown by the method invocation on the proxy instance.



别人返回类型是基本类型,那你返回的也应该是基本类型啊,null就是object类型了,类型找不到,肯定报空指针异常了,除非你把request方法改为object类型。

------解决方案--------------------
int request() 这个函数只能返回 int 相关类型的数据,你改成 Object request() 就可以返回null了。
------解决方案--------------------
这两种类型的代理都会把返回值进行转换,但是InvocationHandler没有对函数返回值做空处理,而MethodInterceptor则会对函数返回值做空处理,所以不会抛出异常。
------解决方案--------------------
所谓的动态代理,其实就是把RealSubject、HelloWorld做了映射,可以参考下面的代码
InvocationHandler创建的

 public Object invoke(Object proxy, Method method, Object[] args)  throws Throwable {
         method.invoke(obj, args);
         return null;  
}

public int request() {
   System.out.println("realsubject");
   return null;              //此时映射成的函数是无法编译的
 }


MethodInterceptor创建的

public Object intercept(Object proxy, Method method, Object[] params, MethodProxy methodProxy) throws Throwable {
    methodProxy.invokeSuper(proxy, params);
   return null; 
}

public int  say() {
 System.out.println(11111111);
 return 0;       //此时映射成的函数返回值 不是 1 而是 0 
 }


当初API的设计者并不是没有考虑到这种情况,这种函数可以定义为void,完全没必要用返回这种无用的参数。
  相关解决方案