今天使用Proxy.newInstance()遇到的坑,NullPointerException

  原因是这样的,今天跟着老师作Calculator接口的动态代理时,Calculator内的方法都是这样的。

然后动态代理方法是这样写的。

结果一直报空指针异常。

但是执行结果没有错,就是报空指针异常,就看了下这个方法的说明。

下面是原文和谷歌翻译内容

Processes a method invocation on a proxy instance and returns the result. This method will be invoked on an invocation handler when a method is invoked on a proxy instance that it is associated with.
Params:
proxy – the proxy instance that the method was invoked on method – the Method instance corresponding to the interface method invoked on the proxy instance. The declaring class of the Method object will be the interface that the method was declared in, which may be a superinterface of the proxy interface that the proxy class inherits the method through. args – an array of objects containing the values of the arguments passed in the method invocation on the proxy instance, or null if interface method takes no arguments. Arguments of primitive types are wrapped in instances of the appropriate primitive wrapper class, such as java.lang.Integer or java.lang.Boolean.
Returns:
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.
Throws:
Throwable – the exception to throw from the method invocation on the proxy instance. The exception's type must be assignable either to any of the exception types declared in the throws clause of the interface method or to the unchecked exception types java.lang.RuntimeException or java.lang.Error. If a checked exception is thrown by this method that is not assignable to any of the exception types declared in the throws clause of the interface method, then an UndeclaredThrowableException containing the exception that was thrown by this method will be thrown by the method invocation on the proxy instance.

谷歌翻译

处理代理实例上的方法调用并返回结果。当在与其关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
参数:
proxy – 在方法上调用该方法的代理实例 method – 对应于在代理实例上调用的接口方法的 Method 实例。
 Method对象的声明类将是声明该方法的接口,该接口可能是代理类继承该方法的代理接口的超接口。 
args – 一个对象数组,其中包含在代理实例上的方法调用中传递的参数值,如果接口方法不接受任何参数,则返回 null。
原始类型的参数被包装在适当的原始包装类的实例中,例如 java.lang.Integer 或 java.lang.Boolean。
回报:
从代理实例上的方法调用返回的值。如果接口方法声明的返回类型是原始类型,那么该方法返回的值必须是对应原始包装类的实例;
否则,它必须是可分配给声明的返回类型的类型。如果此方法返回的值为 null 且接口方法的返回类型为原始类型,则代理实例上的方法调用将引发 NullPointerException。
如果此方法返回的值与上述接口方法声明的返回类型不兼容,则代理实例上的方法调用将抛出 ClassCastException。
抛出:
Throwable – 从代理实例的方法调用中抛出的异常。异常的类型必须可以分配给接口方法的 throws 子句中声明的任何异常类型,或者可以分配给未经检查的异常类型
java.lang.RuntimeException 或 java.lang.Error。
如果此方法抛出了一个不能分配给接口方法的 throws 子句中声明的任何异常类型的已检查异常,
则包含此方法抛出的异常的 UndeclaredThrowableException 将由方法调用抛出代理实例。

关键就在这:

如果接口方法声明的返回类型是原始类型,那么该方法返回的值必须是对应原始包装类的实例;
否则,它必须是可分配给声明的返回类型的类型。如果此方法返回的值为 null 且接口方法的返回类型为原始类型,则代理实例上的方法调用将引发 NullPointerException。

因为我返回了null,而且接口的返回类型是基本数据类型,所以报错。

只要把Calculator接口的返回值改成Integer就行了。但是因为源码debug不了,我不了解为什么这样,只能以后再去了解了。

2023-3-2:补充,知道报错的原因了,方法的返回值为int,所以代理对象的方法返回值也为int,因为这个例子是爆出异常,所以返回的是null,null被当做integer自动拆箱转换成int,使用了Integer.intValue(),又因为为null,自然爆空指针异常。

posted @ 2022-09-08 19:30  午夜·bicycle  阅读(399)  评论(0编辑  收藏  举报