2012-06-24 13 views
7

Mam następujący problem: Mam klasę, próbuję użyć odbicia, aby wywołać jedną z jej chronionych metodami OWN, i otrzymuję wyjątek: java.lang.IllegalAccessException : dostęp do metody odmowyOdmowa dostępu do metody podczas wywoływania metody chronionej podklasą java

Czy ktoś może rzucić trochę światła na to?

Klasa bazowa:

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

} 

Pochodna beton klasy:

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

Czy działa z 'BaseReceiver.class.getDeclaredMethod'? – Thilo

+0

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

+0

@KazekageGaara: to inne pytanie dotyczy metod niedostępnych w inny sposób. Tutaj próbuje przywołać własną metodę. – Thilo

Odpowiedz

15

Protected metody są dostępne tylko z pakietu, sama klasa lub klasy, która rozszerza je.

O ile mogę przypuszczać (na podstawie Exception) twoja rozszerzona klasa (MyReceiver) jest w innym pakiecie niż super klasa (BaseReceiver). Znaczenie:

  1. MyReceiver i BaseReceiver nie jest w tym samym opakowaniu;
  2. BaseReceiver nie rozciąga się na MyReceiver;

Teraz, jak widać na kodzie, robisz: method = this.getClass().getDeclaredMethod("testMethod"); wydaje się, że jest OK, ale to nie jest to, co masz zamiar. Ponieważ ta metoda zwróci metodę MyReceiver.testMethod(), a to nie jest dostępne z BaseReceiver (jak widać, używasz this.getClass(), co zwraca klasę instancji, w tym przypadku MyReceiver).

Można zrobić coś:

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

z tym jesteś pouczając, że chcesz chronić metoda jest ogłoszony na BaseReceiver klasie. Oczywiście po wywołaniu go później pod numerem method.invoke(this); wywołasz metodę nadpisywaną.

Ale nie ma sensu używać refleksji w takim przypadku, ponieważ masz dostępną testMethod(), a wywołanie go (proste jak this.testMethod()) spowoduje wywołanie nadpisanego.

Inną możliwością jest setAccessible(true) od metody jak:

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

+1 'setAccessible (true)' – Bohemian

+0

+1 Wystarczy bezpośrednio wywołać 'testMethod()'. Refleksja to zły pomysł. –

1

Statyczny typ this w BaseReceiver jest BaseReceiver, więc normalnie nie ma dostępu do MyReceiver.testMethod. Poza tym interfejsy API do odczytywania sprawdzają klasę wywołującą, a nie instancję (co samo w sobie jest kluczem do refleksji).

Powinieneś być w stanie używać BaseReceiver.testMethod.

Odbicie jest złym pomysłem w większości (ale nie wszystkich) przypadków, w których jest używane.

Powiązane problemy