Java 代理抛出 NullPointerException

Java Proxy throws NullPointerException

我正在尝试将 ClickListener 注册到 Button。我用的是Vaadin 8,这个监听应该是用Proxy实现的。

final Button button = new Button("Hello");

final Class<?> clickListenerClass = Button.ClickListener.class;
final Object clickListenerInstance = Proxy.newProxyInstance(clickListenerClass.getClassLoader(),
    new Class[] {clickListenerClass}, (proxy, method, args) -> {
        System.out.println("TEST");

        return null;
    });

button.addClickListener((Button.ClickListener)clickListenerInstance);

这是堆栈跟踪(我省略了我的代码。异常发生在上面代码片段的最后一行)。

java.lang.NullPointerException: null
    at com.sun.proxy.$Proxy20.hashCode(Unknown Source)
    at com.vaadin.event.ListenerMethod.hashCode(ListenerMethod.java:571)
    at java.util.HashMap.hash(HashMap.java:339)
    at java.util.HashMap.put(HashMap.java:612)
    at java.util.HashSet.add(HashSet.java:220)
    at com.vaadin.event.EventRouter.addListener(EventRouter.java:64)
    at com.vaadin.server.AbstractClientConnector.addListener(AbstractClientConnector.java:842)
    at com.vaadin.ui.Button.addClickListener(Button.java:333)

您正在 returning null 代理上的任何方法调用。在堆栈跟踪中,您可以看到 Vaadin 根据您的实现调用 returns nullhashCode 方法。来自 InvocationHandler Javadocs,invoke 方法 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.

因此,例如,您需要对目标对象的引用,从中调用方法,然后 return 结果。 https://www.baeldung.com/java-dynamic-proxies

上有一个很好的教程