2011-12-09 12 views
16

Creé una enumeración con una variable de miembro privada. Cuando intento acceder a la variable miembro, la compilación indica 'No se puede hacer una referencia estática al campo no estático memberVariable'.No se puede hacer una referencia estática al miembro de campo no estático Variable con la variable privada

Si la variable no es privada (por ejemplo protegida o protegida por paquete) compila bien. No entiendo qué tiene que ver el alcance de la variable con el tipo (estático, no estático) de la función abstracta implementada.

¿Alguien me puede aclarar?

public enum EnumWithAbstractMethodAndMembers { 
    TheOneAndOnly(1) { 
     @Override 
     public int addValue(final int value) { 
      return memberVariable + value; 
     } 
    }; 

    private final int memberVariable; 

    private EnumWithAbstractMethodAndMembers(final int memberVariable) { 
     this.memberVariable = memberVariable; 
    } 

    abstract int addValue(int value); 

} 

Respuesta

19

El mensaje de error es confuso.

El problema es que cuando se da un código de valor enum, se está creando una subclase anónima de la enumeración. (Su clase será EnumWithAbstractMethodAndMembers$1) Una subclase no puede acceder a los miembros privados de su superclase, sin embargo las clases anidadas pueden hacerlo a través del método de acceso generado. Debería poder acceder al campo privado y parece que el mensaje de error que le da es erróneo.

BTW Puede utilizar esto, pero no debería necesitar en mi humilde opinión.

public int addValue(final int value) { 
     return super.memberVariable + value; 
    } 

Aquí es un ejemplo más corto Voy a registrar como un error en el mensaje de error, ya que no conduce a una solución al problema.

public enum MyEnum { 
    One { 
     public int getMemberVariableFailes() { 
      // error: non-static variable memberVariable cannot be referenced from a static context 
      return memberVariable; 
     } 

     public int getMemberVariable2OK() { 
      return memberVariable2; 
     } 

     public int getMemberVariableOK() { 
      return super.memberVariable; 
     } 
    }; 

    private final int memberVariable = 1; 
    final int memberVariable2 = 1; 
} 

base en la retroalimentación de Tom Hawkin, este ejemplo se obtiene el mismo mensaje de error.

public class MyNotEnum { 
    // this is the static context in which the anonymous is created 
    public static final MyNotEnum One = new MyNotEnum() { 
     public int getMemberVariableFailes() { 
      // error: non-static variable memberVariable cannot be referenced from a static context 
      return memberVariable; 
     } 

     public int getMemberVariableOK() { 
      return super.memberVariable; 
     } 
    }; 
    private final int memberVariable = 1; 
} 

para la comparación

public class MyNotEnum { 
    public class NestedNotEnum extends MyNotEnum { 
     public int getMemberVariableFailes() { 
      // compiles just fine. 
      return memberVariable; 
     } 

     public int getMemberVariableOK() { 
      return super.memberVariable; 
     } 
    } 
    private final int memberVariable = 1; 
} 
+0

de sonido razonable. ¡Gracias por la respuesta y la pista con 'super'! – Andreas

+0

Lo he registrado como un error 'javac'. –

+1

Dicen que debería ser visible en un par de días. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7119746 Noté que Oracle acepta mis errores ** mucho ** más rápido que Sun. –

0

La principal causa de error es: que está tratando de hacer referencia a la variable privada (memberVariable) de la superclase de la clase de implementación interna.

Para hacer que el código libre de errores, puede realizar una de las siguientes:

  • usted tiene que utilizar super.memberVariable desde memberVariable es no es local a TheOnlyAndOnly()
  • puede hacer int memberVariablepública.
  • que puede hacer:

    TheOneAndOnly(1) { 
        int memberVariable=4; 
        @Override 
        public int addValue(final int value) { 
         return memberVariable + value; 
        } 
    }; 
    
3

Un problema similar se cubre en Puzzlers Java por Josh Bloch y Neal Gafter (no sé donde cualquiera de mis copias es, así que no puedo darte una referencia exacta).

No hay nada especial acerca de enums. Cualquier clase interna anónima (o local) en un contexto estático funcionará. Las reglas son que la clase externa se considera antes de la súper clase. Esto tiene mucho sentido para tales clases en un contexto no estático.Si al cambiar el contexto a estático se cambió qué variable se buscó, existe la posibilidad de introducir "confusión" en el tiempo de ejecución (C++ es mucho más agresivo con este tipo de regla).

Una clase interna que amplía una clase externa tiene acceso a los campos de instancia privada de la clase externa, ya sea a través de this o de alguna otra instancia.

Como se nos permite el acceso, tenemos que especificar de alguna manera que queremos pasar por el interior esto en lugar de esto externo. Como Peter Lawrey señala super.member hará. También puede seleccionar el interior de este, y luego usar esa expresión:

 return ((EnumWithAbstractMethodAndMembers)this).memberVariable + value; 

O

 EnumWithAbstractMethodAndMembers innerThis = this; 
     return innerThis.memberVariable + value; 
Cuestiones relacionadas