исключение доступа при вызове метода анонимного класса с помощью отражения Java

Я пытаюсь использовать диспетчера события, чтобы позволить модели уведомлять подписанных слушателей, когда она изменяется. диспетчер события получает класс обработчика и имя метода для вызова во время отправки. предъявитель подписывается на образцовые изменения, и обеспечьте реализацию Обработчика, которую назовут на изменениях.

Вот код (я сожалею, что это немного длинно).

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());
            }
        }
    }
}

Модель:

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();
    }
}

ModelChangedHandler:

package model;

public interface ModelChangedHandler {
    void modelChanged();
}

Предъявитель:

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");
            }
        });
    }
}

Основной:

package main;

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

Теперь, я ожидаю добираться, "модель изменила" сообщение. Однако я получаю java.lang. IllegalAccessException: Класс utils. EventDispatcher не может получить доступ к члену предъявителя класса. 1 Presenter$ с модификаторами "общественность".

Я понимаю, что класс для обвинения является анонимным классом, который я создал в предъявителе, однако я не знаю, как больше делать его 'общественностью', чем это в настоящее время. Если я заменяю его именованным вложенным классом, это, кажется, работает. Это также работает, если Предъявитель и EventDispatcher находятся в том же пакете, но я не могу признать что (несколько предъявителей в различных пакетах должны использовать EventDispatcher),

какие-либо идеи?

5
задан Asaf David 25 March 2011 в 22:19
поделиться

3 ответа

Это ошибка JVM ( ошибка 4819108 )

Временное решение - вызвать method.setAccessible ( true) перед вызовом метода method.invoke (listener)

10
ответ дан 13 December 2019 в 05:32
поделиться

Я предполагаю, что анонимный класс всегда частный , но я не нашел четкого заявления об этом в Спецификации языка Java (я смотрел в §15.9.5)

В Java , если тип недоступен, его члены тоже.

Если вам нравится черная магия, вы можете отключить проверку доступа с помощью method.setAccessible (true) . В качестве альтернативы вы можете потребовать, чтобы ваши обработчики событий назывались классами или рассматриваемый метод был объявлен в доступных типах.

1
ответ дан 13 December 2019 в 05:32
поделиться

В таком случае использовать отражение - действительно плохая идея. Просто позвольте диспетчеру вызвать требуемый метод. Если вам нужно несколько диспетчеров для вызова разных методов, просто подклассифицируйте их.

В Java отсутствуют закрытия, но помощь уже в пути!

0
ответ дан 13 December 2019 в 05:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: