预计将'String'基本类型拆箱,但返回null

时间:2018-08-29 17:41:28

标签: java android reflection

我正在尝试使用Java Reflection来调用将回调作为参数的方法。我使用Java Reflection实例化所有对象。另外,我使用Java Dynamic Proxy Class作为回调参数。

我有几种奇怪的行为:

  1. java.lang.reflect.Proxy.newProxyInstance()方法返回null

  2. 以下几种错误,具体取决于我尝试的以下代码版本:

    1. Expected to unbox a 'int' primitive type but was returned null

    2. Expected to unbox a 'String' primitive type but was returned null

这是我想实例化为Java动态代理类的匿名对象的接口:

public interface MyListener {
    void onEvent(String eventName);
}

这是我如何通过newProxyInstance()实例化接口的方法:

Object callbackObject = null;

try {
    Class callbackClass = Class.forName("com.example.MyListener");

    Class[] interfaceArray = new Class[]{callbackClass};

    InvocationHandler invocationHandler = new InvocationHandler() {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (method.getName().equals("onMyEvent")) {
                Log.d(TAG, "InvocationHandler.invoke onMyEvent");
            }
            return null;
        }
    };

    callbackObject = java.lang.reflect.Proxy.newProxyInstance(
            this.getClass().getClassLoader(),
            interfaceArray,
            invocationHandler);
}
catch (Throwable t) {
    Log.e(TAG, "newProxyInstance got exception [" + t + "] caused by [" + t.getCause() + "]");
}

Log.d(TAG, "callbackObject=[" + callbackObject + "]");

if (null == callbackObject) {
    Log.e(TAG, "callbackObject is null according to null check");
}
else {
    Log.d(TAG, "callbackObject is NOT null according to null check");
}

关于callbackObject是否为null的日志消息似乎冲突:

callbackObject=[null]
callbackObject is NOT null according to null check

根据Why does newInstance() return null?newProxyInstance()不可能返回null,因为它从newInstance()获取值。

那么newProxyInstance()的结果如何是null而不是null?这些错误消息,例如Expected to unbox a 'int' primitive type but was returned null是什么意思?

1 个答案:

答案 0 :(得分:0)

解决方案:java.lang.reflect.Proxy.newProxyInstance()方法返回null

我发现newProxyInstance()返回的对象不是 null,它似乎只是null。打印出返回值的日志消息说它为null,因为Java隐式调用对象上的toString()。但是由于该对象是Proxy,因此它将转发到我的InvocationHandler。真正的问题是我的InvocationHandler总是返回null。我认为null是合适的,因为onEvent()方法返回void。但是,我没想到toString()也将转发到InvocationHandler

解决方案:Expected to unbox a 'int' primitive type but was returned null

在尝试调试明显的null时,我最终尝试在newProxyInstance()返回的对象上调用其他方法,例如hashcode()getClass()。所有这些方法的所有都转发到了InvocationHandler,因为它们并没有期望它们,因此它只返回了null的所有内容。由于null不是有效的int,因此hashcode()函数导致错误Expected to unbox a 'int' primitive type but was returned null

通过使我的InvocationHandler更加健壮,我可以消除此错误:

    InvocationHandler invocationHandler = new InvocationHandler() {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (method.getName().equals("onMyEvent")) {
                Log.d(TAG, "InvocationHandler.invoke onMyEvent");
                return null;
            }
            else if (String.class == method.getReturnType()) {
                return "";
            }
            else if (Integer.class == method.getReturnType()) {
                return Integer.valueOf(0);
            }
            else if (int.class == method.getReturnType()) {
                return 0;
            }
            else if (Boolean.class == method.getReturnType()) {
                return Boolean.FALSE;
            }
            else if (boolean.class == method.getReturnType()) {
                return false;
            }
            else {
                return null;
            }
        }
    };

但是,对我来说,实际的解决方案是删除称为hashcode()等的调试代码,并相信newProxyInstance()的结果不是null。而且将来,请记住InvocationHandler会转发所有方法调用。

感谢artaxerxe's solution for Proxy object throws NullPointerException为我提供了见识。