2010-08-02 22 views
10

Tengo dos clases.IllegalAccessError: accediendo a un método protegido

clase A tiene el método protegido m(), a es una instancia de A.

La clase B está en el mismo paquete que la clase A.

Estoy tratando de acceder a.m() pero yo estoy haciendo IllegalAccessError ...

¿Qué ocurre?

+4

Produzca un programa breve pero completo que demuestre el problema. Esto suena muy extraño. ¿Tiene alguna ofuscación, etc. involucrado? –

Respuesta

18

El compilador debería detectar errores como este. Como aparentemente está obteniendo esto en tiempo de ejecución, algo extraño ha sucedido. Probablemente haya cambiado el código fuente pero recompilado completamente.

Otro problema potencial, pero oscuro, es cargar las clases a través de diferentes cargadores de clases. Las clases cargadas desde diferentes cargadores de clases estarán en diferentes paquetes, incluso si el nombre del paquete es el mismo (de la misma manera que las clases con el mismo nombre cargado por diferentes cargadores de clases serán clases diferentes).

-1

Tiene que funcionar, ver el siguiente ejemplo que funciona 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(); 
    } 
} 

que imprime el mensaje deseado: "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."

Ver Controlling Access to Members of a Class.

+2

"El modificador protegido especifica que solo se puede acceder al miembro dentro de su propio paquete (como con paquete-privado) y, además, por una subclase de su clase en otro paquete". http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html –

+0

O déjelo con acceso predeterminado (es decir, sin especificador de acceso) para permitir el acceso al paquete. – Scott

+0

cambié el contenido de la respuesta, el contenido anterior tenía errores, lo siento por eso y thx @fd; ¿Estás seguro de que tu clase B está realmente en el mismo paquete que la clase A? –

-2

compilador debería detectar errores como este. Como está obteniendo esto en tiempo de ejecución, algo malo ha sucedido. Lo más probable es que haya cambiado el código fuente que está completamente recompilado.

Debe funcionar. Aquí está un ejemplo de ejecución -

**

  • CLASE A

**

package com.test; 

public class A { 

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

} 

**

  • CLASE B

**

package com.test; 

public class B{ 

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

} 

que imprime la cadena esperada

Hi Stackoverflow

15

Esto puede suceder si las clases A y B son cargados por diferentes cargador de clases. El jvm considera que estas clases están en diferentes "paquetes de tiempo de ejecución". Citando de the jvm specification, sección 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.

Y en la sección 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

sospecho que esto podría estar causando mi problema, pero no estoy seguro de en qué parte de la pila se extraerá un cargador de segunda clase o cómo depurarlo. Pero miraré alrededor ... –

+0

Encontré esta respuesta después de buscar en Google sobre otro problema en el que mi clase estaba en el mismo paquete con nombre, pero con un paquete de tiempo de ejecución diferente. ¡Esto hace que las cosas tengan mucho más sentido! +1 – vergenzt

Cuestiones relacionadas