2012-06-24 1 views
7

У меня есть следующая проблема: у меня есть класс, пытающийся использовать отражение для вызова одного из своих защищенных OWN-методов, и я получаю исключение: java.lang.IllegalAccessException : доступ к методу отклоненметод доступа запрещен при вызове метода защиты подкласса java

Может кто-то может пролить свет на это?

Базовый класс:

public abstract class BaseReceiver extends BroadcastReceiver { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     // invoke the correct event method: 
     Method method; 
     try { 
      method = this.getClass().getDeclaredMethod("testMethod"); 
      method.invoke(this); 
     } catch (Throwable ex) { 
      // ... display exception message 
     } 
    } 

    protected void testMethod() { 
    } 

} 

Производный класс бетона:

class MyReceiver extends BaseReceiver { 
    @Override 
    protected void testMethod() { 
     // display error message 
    } 
} 
+0

Работает ли он с 'BaseReceiver.class.getDeclaredMethod'? – Thilo

+0

http: // stackoverflow.com/questions/5184284/illegalaccessexception-on-use-reflection –

+0

@KazekageGaara: этот другой вопрос касается методов, недоступных для других. Здесь он пытается назвать свой метод. – Thilo

ответ

15

Protected методы доступны только из пакета, то сам класс или классы, расширяет его.

Насколько я могу предположить (на основе Exception) ваш расширенный класс (MyReceiver) находится в другом пакете, затем суперклассе (BaseReceiver). Значение:

  1. MyReceiver и BaseReceiver не в том же пакете;
  2. BaseReceiver не распространяется MyReceiver;

Теперь, как вы можете видеть на своем коде, вы делаете: method = this.getClass().getDeclaredMethod("testMethod"); Это похоже на одобрение, но это не то, что вы намереваетесь. Поскольку этот метод будет возвращать метод MyReceiver.testMethod(), и это не доступно из BaseReceiver (как вы можете видеть, вы используете this.getClass(), что возвращает класс экземпляра, в данном случае MyReceiver).

Вы могли бы сделать что-то:

... 
method = BaseReceiver.class.getDeclaredMethod("testMethod"); 
... 

с этим вы инструктирования, что вы хотите, чтобы защищенный метод был объявлен на BaseReceiver класса. Конечно, когда вы вызываете его позже с method.invoke(this);, вы вызываете переопределенный метод.

Но не имеет смысла использовать отражение в таком случае, так как у вас есть testMethod() и вызывать его (просто как this.testMethod()) вы будете ссылаться на переопределенный.

Другая возможность состоит в том, чтобы setAccessible(true) по методу, как:

method = getClass().getDeclaredMethod("testMethod"); 
method.setAccessible(true); 
method.invoke(this); 
+4

+1 'setAccessible (true)' – Bohemian

+0

+1 Просто вызовите 'testMethod()' непосредственно. Отражение - плохая идея. –

1

Статический тип this в BaseReceiver является BaseReceiver, так что вы обычно не имеют доступа к MyReceiver.testMethod. Кроме того, API-интерфейсы отражения проверяют класс вызывающего абонента, а не экземпляр (который сам по себе является орехом, учитывая, что такое отражение).

Вы должны иметь возможность использовать BaseReceiver.testMethod.

Отражение - плохая идея в большинстве (но не всех) случаях, в которых она используется.