java的JDK的动态代理的一个疑惑

J2EE 码拜 10年前 (2015-04-13) 978次浏览 0个评论
 

我刚刚在看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;否则报空指针异常
 

java的JDK的动态代理的一个疑惑
哎呀 我打代码打的好辛苦 各位指点下吧
java的JDK的动态代理的一个疑惑
10分
int request();
这个肯定不能是null,换成Object试试
java的JDK的动态代理的一个疑惑
debug一下,看在哪里爆的空指针,然后你的困惑就解决了
java的JDK的动态代理的一个疑惑
10分
本帖最后由 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类型。

java的JDK的动态代理的一个疑惑
10分
int request() 这个函数只能返回 int 相关类型的数据,你改成 Object request() 就可以返回null了。
java的JDK的动态代理的一个疑惑
引用 4 楼 fangmingshijie 的回复:

这个没有什么异议吧,看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类型。

确实把类型改成Object就运行不报错了啊
public class HelloWorld {
public void sayHelloWorld() {
System.out.println(“HelloWorld!”);
}
public int  say() {
System.out.println(11111111);
return 1;
}
}

public class CglibProxy implements MethodInterceptor {
private Object obj;

public Object createProxy(Object target) {
this.obj = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.obj.getClass());
enhancer.setCallback(this);
enhancer.setClassLoader(target.getClass().getClassLoader());
return enhancer.create();
}

public Object intercept(Object proxy, Method method, Object[] params,
MethodProxy methodProxy) throws Throwable {
System.out.println(“增强前”);
Object result = methodProxy.invokeSuper(proxy, params);
System.out.println(“增强后”);
return null; //这里是null不报错的
}

}

public class Test {
public static void main(String[] args) {
HelloWorld hello = new HelloWorld();
CglibProxy cglibProxy = new CglibProxy();
HelloWorld hw=(HelloWorld) cglibProxy.createProxy(hello);
hw.sayHelloWorld();
hw.say();
}

那为啥我要cjlib动态代理  返回的函数类型也是int     返回的也是null  就不报错呢  这是为啥呢

java的JDK的动态代理的一个疑惑
引用 5 楼 huasuoworld 的回复:

int request() 这个函数只能返回 int 相关类型的数据,你改成 Object request() 就可以返回null了。

确实把类型改成Object就运行不报错了啊 public class HelloWorld {
 public void sayHelloWorld() {
 System.out.println(“HelloWorld!”);
 }
 public int  say() {
 System.out.println(11111111);
 return 1;
 }
 }
 

public class CglibProxy implements MethodInterceptor {
 private Object obj;
 
public Object createProxy(Object target) {
 this.obj = target;
 Enhancer enhancer = new Enhancer();
 enhancer.setSuperclass(this.obj.getClass());
 enhancer.setCallback(this);
 enhancer.setClassLoader(target.getClass().getClassLoader());
 return enhancer.create();
 }
 
public Object intercept(Object proxy, Method method, Object[] params,
 MethodProxy methodProxy) throws Throwable {
 System.out.println(“增强前”);
Object result = methodProxy.invokeSuper(proxy, params);
 System.out.println(“增强后”);
return null; //这里是null不报错的
}
 
}
 
public class Test {
 public static void main(String[] args) {
 HelloWorld hello = new HelloWorld();
 CglibProxy cglibProxy = new CglibProxy();
 HelloWorld hw=(HelloWorld) cglibProxy.createProxy(hello);
 hw.sayHelloWorld();
 hw.say();
 }
 } 
 那为啥我要cjlib动态代理  返回的函数类型也是int     返回的也是null  就不报错呢  这是为啥呢 

java的JDK的动态代理的一个疑惑
引用 2 楼 xiaopeipei2004 的回复:

int request();
这个肯定不能是null,换成Object试试

确实把类型改成Object就运行不报错了啊 public class HelloWorld {
 public void sayHelloWorld() {
 System.out.println(“HelloWorld!”);
 }
 public int  say() {
 System.out.println(11111111);
 return 1;
 }
 }
 

public class CglibProxy implements MethodInterceptor {
 private Object obj;
 
public Object createProxy(Object target) {
 this.obj = target;
 Enhancer enhancer = new Enhancer();
 enhancer.setSuperclass(this.obj.getClass());
 enhancer.setCallback(this);
 enhancer.setClassLoader(target.getClass().getClassLoader());
 return enhancer.create();
 }
 
public Object intercept(Object proxy, Method method, Object[] params,
 MethodProxy methodProxy) throws Throwable {
 System.out.println(“增强前”);
Object result = methodProxy.invokeSuper(proxy, params);
 System.out.println(“增强后”);
return null; //这里是null不报错的
}
 
}
 
public class Test {
 public static void main(String[] args) {
 HelloWorld hello = new HelloWorld();
 CglibProxy cglibProxy = new CglibProxy();
 HelloWorld hw=(HelloWorld) cglibProxy.createProxy(hello);
 hw.sayHelloWorld();
 hw.say();
 }
 } 
 那为啥我要cjlib动态代理  返回的函数类型也是int     返回的也是null  就不报错呢  这是为啥呢 

java的JDK的动态代理的一个疑惑
有没有异常是根据api设计而来的,两者没有对比度。
java的JDK的动态代理的一个疑惑
10分
这两种类型的代理都会把返回值进行转换,但是InvocationHandler没有对函数返回值做空处理,而MethodInterceptor则会对函数返回值做空处理,所以不会抛出异常。
java的JDK的动态代理的一个疑惑
引用 9 楼 fangmingshijie 的回复:

有没有异常是根据api设计而来的,两者没有对比度。

那用JDK的代理时候为什么能把null赋值给Object啊 就不报异常了啊

java的JDK的动态代理的一个疑惑
引用 10 楼 huasuoworld 的回复:

这两种类型的代理都会把返回值进行转换,但是InvocationHandler没有对函数返回值做空处理,而MethodInterceptor则会对函数返回值做空处理,所以不会抛出异常。

那用JDK的代理时候为什么能把null赋值给Object啊 就不报异常了啊

java的JDK的动态代理的一个疑惑
引用 11 楼 hadoop000 的回复:
Quote: 引用 9 楼 fangmingshijie 的回复:

有没有异常是根据api设计而来的,两者没有对比度。

那用JDK的代理时候为什么能把null赋值给Object啊 就不报异常了啊

能不能好好看看api,再来问。

java的JDK的动态代理的一个疑惑
引用 12 楼 hadoop000 的回复:
Quote: 引用 10 楼 huasuoworld 的回复:

这两种类型的代理都会把返回值进行转换,但是InvocationHandler没有对函数返回值做空处理,而MethodInterceptor则会对函数返回值做空处理,所以不会抛出异常。

那用JDK的代理时候为什么能把null赋值给Object啊 就不报异常了啊

因为Object obj = null 是可以通过编译的,但是 int i = null 则无法通过编译。

java的JDK的动态代理的一个疑惑
60分
所谓的动态代理,其实就是把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,完全没必要用返回这种无用的参数。

java的JDK的动态代理的一个疑惑
引用 15 楼 huasuoworld 的回复:

所谓的动态代理,其实就是把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,完全没必要用返回这种无用的参数。

厉害啊  我自己在想想

java的JDK的动态代理的一个疑惑
引用 13 楼 fangmingshijie 的回复:
Quote: 引用 11 楼 hadoop000 的回复:
Quote: 引用 9 楼 fangmingshijie 的回复:

有没有异常是根据api设计而来的,两者没有对比度。

那用JDK的代理时候为什么能把null赋值给Object啊 就不报异常了啊

能不能好好看看api,再来问。

一直不太明白怎么可能API啊


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明java的JDK的动态代理的一个疑惑
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!