使用java反射调用匿名类的方法时访问异常

Asa*_*vid 5 java reflection events anonymous-class access-levels

我正在尝试使用事件调度程序来允许模型在更改时通知已订阅的侦听器.事件调度程序接收在调度期间调用的处理程序类和方法名称.演示者订阅模型更改并提供要在更改时调用的Handler实现.

这是代码(对不起,它有点长).

EventDispacther:

package utils;

public class EventDispatcher<T> {
    List<T> listeners;
    private String methodName;

    public EventDispatcher(String methodName) {
        listeners = new ArrayList<T>();
        this.methodName = methodName;
    }

    public void add(T listener) {
        listeners.add(listener);
    }

    public void dispatch() {
        for (T listener : listeners) {
            try {
                Method method = listener.getClass().getMethod(methodName);
                method.invoke(listener);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

模型:

package model;

public class Model {
    private EventDispatcher<ModelChangedHandler> dispatcher;

    public Model() {
        dispatcher = new EventDispatcher<ModelChangedHandler>("modelChanged");
    }

    public void whenModelChange(ModelChangedHandler handler) {
        dispatcher.add(handler);
    }

    public void change() {
        dispatcher.dispatch();
    }
}
Run Code Online (Sandbox Code Playgroud)

ModelChangedHandler:

package model;

public interface ModelChangedHandler {
    void modelChanged();
}
Run Code Online (Sandbox Code Playgroud)

主持人:

package presenter;

public class Presenter {

    private final Model model;

    public Presenter(Model model) {
        this.model = model;
        this.model.whenModelChange(new ModelChangedHandler() {

            @Override
            public void modelChanged() {
                System.out.println("model changed");
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

主要:

package main;

public class Main {
    public static void main(String[] args) {
        Model model = new Model();
        Presenter presenter = new Presenter(model);
        model.change();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我希望得到"模型改变"的消息.但是,我得到一个java.lang.IllegalAccessException:类utils.EventDispatcher无法使用修饰符"public"访问类presenter.Presenter $ 1的成员.

我理解,应该责备的是我在演示者中创建的匿名类,但是我不知道如何让它比现在更"公开".如果我用命名的嵌套类替换它,它似乎工作.如果Presenter和EventDispatcher在同一个包中,它也可以工作,但我不能允许(不同包中的几个演示者应该使用EventDispatcher)

有任何想法吗?

Rob*_*ser 10

这是JVM中的一个错误(bug 4819108)

解决方法是在调用method.setAccessible(true)之前调用method.invoke(listener)