IllegalAccessException при использовании вызова динамических методов - PullRequest
10 голосов
/ 28 мая 2011

Я пытаюсь использовать Reflection в Java, но получаю странную ошибку.Каковы возможные проблемы, когда я получаю сообщение об ошибке:

java.lang.IllegalAccessException: Class com.myapp.core.utils.EventDispatcher can not access a member of class appApp$1 with modifiers "public"
at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)

Я просто пытаюсь создать свой собственный класс EventDispatcher и внутри него, часть, которую я использовал отражение, которая также является строкой кода, котораяпричина проблемы:

public void dispatchEvent(Event e, String callMethName) {
IEventListener list = ((IEventListener)listeners[i]);
                list.getClass().getMethod(callMethName, Event.class).invoke(list, e);
}

В моем основном классе у меня есть то, что вызывает addListener, который просто добавит слушателя в список в классе EventDispatcher следующим образом:

try {
obj.addListener("onTestHandler", new MyTestEventListener(){
    @Override
    public void onTestHandler(Event e) {
        System.out.println("hello!");
    }
});
} catch (SecurityException e) {
    e.printStackTrace();
}

Таким образом, первый параметр, который говорит «onTestHandler», будет передаваться в класс EventDispatcher и в конечном итоге как часть параметра callMethName в методе dispatchEvent, который будет вызывать метод динамически.

Передача методов и все правильно.У той части, которая имеет отражение, есть проблемы.Кажется, можно найти метод.Но по какой-то причине выдает исключение IllegalAccessException и не может вызвать метод.

Почему это так?

Спасибо.

Ответы [ 2 ]

16 голосов
/ 28 мая 2011

Я подозреваю, что анонимный класс (appApp$1), который реализует MyTestEventListener, имеет видимость пакета и что код отражения находится в другом пакете.

Для этого кода:

package foo.p1;
public class Target {
  public static interface Foo {
    public void bar();
  }

  public static Foo newFoo() {
    return new Foo() {
      @Override
      public void bar() { 
      }
    };
  }
}

Этот код завершится ошибкой, поскольку тип времени выполнения, возвращаемый newFoo(), не является общедоступным классом:

package foo.p2;
import foo.p1.Target;
public class Main {
  public static void main(String[] args) throws Exception {
    Target.Foo foo = Target.newFoo();
    foo.getClass()
        .getMethod("bar")
        .invoke(foo);
  }
}

Это можно преодолеть, установив метод как доступный:

Target.Foo foo = Target.newFoo();
Method m = foo.getClass()
    .getMethod("bar");
m.setAccessible(true);
m.invoke(foo);

Или с помощью метода из открытого интерфейса:

Target.Foo foo = Target.newFoo();
Target.Foo.class.getMethod("bar")
    .invoke(foo);
3 голосов
/ 28 мая 2011

Доступ к анонимным классам очень ограничен. Вместо того, чтобы просто использовать list.getClass(), вы должны попытаться найти неанонимный суперкласс или интерфейс объекта, который имеет нужный метод, а затем вызвать метод изэтот класс вместо анонимного ..

Я бы также предложил вам выполнить этот поиск во время добавления прослушивателя и сохранения результата.Использовать отражение довольно дорого, поэтому все будет работать быстрее.Не менее важно, что если вы сделаете опечатку в имени метода, вы получите ошибку при добавлении прослушивателя, а не случайно в будущем. Будет гораздо проще найти проблему следующим образом:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...