2010-08-02 6 views
10

J'ai deux classes.IllegalAccessError: accéder à une méthode protégée

classe A a méthode protégée m(), a est une instance de A. La classe B appartient au même groupe que la classe A.

Je suis en train d'accéder a.m() mais je reçois IllegalAccessError ...

Qu'est-ce qui ne va pas?

+4

Veuillez produire un programme court mais complet qui illustre le problème. Cela semble très étrange. Avez-vous une obfuscation etc impliqué? –

Répondre

18

Le compilateur doit détecter les erreurs de ce type. Comme vous le voyez apparemment à l'exécution, quelque chose d'étrange est arrivé. Vous avez probablement modifié le code source mais vous l'avez entièrement recompilé.

Un autre problème potentiel, mais obscur, est le chargement des classes via différents chargeurs de classe. Les classes chargées à partir de différents chargeurs de classes seront dans des paquets différents même si le nom du paquet est le même (de la même manière que les classes portant le même nom chargées par des chargeurs de classe différents seront des classes différentes).

-1

Il doit travailler, voir l'exemple suivant qui fonctionne très bien:

package com.stackoverflow; 

public class TEST 
{ 
    static class A { 
    protected void m() 
    { 
     System.out.println("hello from A.m()"); 
    } 
    } 

    static class B { 

    public B() 
    { 
     a.m(); 
    } 

    private A a = new A(); 
    } 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) 
    { 
    B b = new B(); 
    } 
} 

qui imprime le message voulu: "hello from A.m()"

"The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package."

Voir Controlling Access to Members of a Class.

+2

"Le modificateur protected spécifie que le membre ne peut être accédé que dans son propre package (comme avec package-private) et, en outre, par une sous-classe de sa classe dans un autre package." http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html –

+0

Ou laissez-le avec un accès par défaut (c'est-à-dire sans spécificateur d'accès) pour autoriser l'accès au package. – Scott

+0

j'ai changé le contenu de la réponse, le contenu précédent était bogué, désolé pour cela et thx @fd; Etes-vous sûr que votre classe B est vraiment dans le même paquet que la classe A? –

-2

Le compilateur doit détecter les erreurs de ce type. Comme vous l'obtenez à l'exécution, quelque chose de mal est arrivé. Très probablement vous avez changé le code source qui est entièrement recompilé.

Cela doit fonctionner. Voici un exemple en cours d'exécution -

**

  • CLASSE A

**

package com.test; 

public class A { 

    protected void m(){ 
    System.out.println("Hi Stackoverflow"); 
} 

} 

**

  • CLASSE B

**

package com.test; 

public class B{ 

public static void main(String[] args) { 
    A a = new A(); 
    a.m(); 
} 

} 

qui imprime la chaîne attendue

Hi Stackoverflow

15

Cela peut se produire si les classes A et B sont chargés par différentes classloader. Le jvm considère alors que ces classes sont dans des "paquets d'exécution" différents. Je cite the jvm specification, section 5.3:

At run time, a class or interface is determined not by its name alone, but by a pair: its fully qualified name and its defining class loader. Each such class or interface belongs to a single runtime package. The runtime package of a class or interface is determined by the package name and defining class loader of the class or interface.

Et dans la section 5.4.4:

A field or method R is accessible to a class or interface D if and only if any of the following conditions is true:

...

R is either protected or package private (that is, neither public nor protected nor private), and is declared by a class in the same runtime package as D.

+0

Je suppose que cela pourrait causer mon problème, mais je ne sais pas où dans la pile un chargeur de seconde classe serait tiré ou comment déboguer. Mais je vais chercher ... –

+0

J'ai trouvé cette réponse après quelques recherches sur un autre problème dans lequel ma classe était dans le même paquet nommé, mais un paquet d'exécution différent. Cela rend les choses tellement plus sensées! +1 – vergenzt

Questions connexes