2009-02-24 13 views
10

El azucar de sintaxis proporcionado por la instalación enum de Java a veces puede ser un poco confuso. Considere este ejemplo, que no se compila:Contexto estático en la definición de enumeración

public enum TestEnum { 

    FOO("foo") { 
     public void foo() { 
      helper(); // <- compiler error 
     } 
    }; 

    String name; 
    TestEnum(String name) { 
     this.name = name; 
    } 

    public abstract void foo(); 

    private void helper(){ 
     // do stuff (using this.name, so must not be static) 
    } 
} 

¿Alguien puede explicar por qué el compilador dice

método 'helper()' no estáticos no pueden ser referenciadas desde un contexto estático

¿Cómo está exactamente este contexto estático?

Usted puede hacer esta compilación cambiando la llamada a this.helper() (en este caso es un punto confuso:? Si es que realmente estamos en un "contexto estático", como el compilador indica, ¿cómo se puede "this" trabajar) o por aumentando la visibilidad de helper() al nivel predeterminado. ¿Cual preferirías? Además, siéntase libre de sugerir un título de pregunta mejor :-)

Editar: He encontrado some discussion about this - pero no hay respuestas reales. Mi colega piensa que el hecho de que this.helper() funcione es en realidad un error del compilador. Y de hecho, con las versiones Java más recientes parece que no funciona (aunque super.helper() sí): "no se puede encontrar el símbolo helper()". (Aunque hay algo raro sucediendo: después de probar con diferentes versiones de Java no puedo obtener this.helper() para compilar de nuevo con ninguno de ellos ...)

Respuesta

0

Hay un article mencionando este problema, lamentablemente está en alemán. Tal vez aún puedas extraer alguna información útil.

EDITAR: Parece ser un problema algo diferente al suyo. Todavía no entiendo el comportamiento de tu ejemplo, que también veo aquí.

3

Algo como esto está cubierto en el libro Puzzlers de Java. IIRC, el contexto de la clase externa siempre se mira antes de la súper clase. En este caso, se encuentra el ayudante. Pero estamos construyendo el valor en un contexto estático (efectivamente hay un private static final antes de FOO). De ahí el error.

Probar super.helper();.

+0

Tengo el libro; ¿Qué rompecabezas quieres decir? (No pude encontrarlo rápidamente.) – Jonik

+0

Ambas copias del libro están guardadas en cajas en alguna parte, así que no tengo ni idea. –

2

Si traduzco su enumeración en su estructura de clases que se verá aproximadamente así:

public abstract class TestEnum { 

    public static final TestEnum FOO = new FOO("foo") { 
    public void foo() { 
     helper(); // <- compiler error 
    } 
}; 

    String name; 
    TestEnum(String name) { 
     this.name = name; 
    } 

    public abstract void foo(); 

    private void helper(){ 
    // do stuff (using this.name, so must not be static) 
    } 

}

El FOO instancia es una clase que se extiende anynomous TestEnum. Es por eso que creo que no puedes acceder a helper(), porque es privado. Entonces this.helper() probablemente no debería funcionar. No estoy seguro de por qué incluso super.helper() funciona, pero tal vez enum le da acceso privado a los padres.

En cuanto al error de contexto estático, acepto que el mensaje de error no parece tener sentido.

+0

Nitpick: con "nuevo FOO" ¿quisiste decir "nuevo TestEnum"? – Jonik

+0

sí atrapó eso también ... gracias – richs

8

El mensaje de error es engañoso, simplemente haga que helper esté protegido y funcionará.

protected void helper(){ 
    // can be called from subclasses (such as FOO) since it is not private 
} 
1

Puede pensar en cada enumeración constante como la única instancia de una subclase de la clase enum.Al igual que con las clases "normales", las "subclases" enum no pueden acceder a los miembros privados de la "superclase" enum. (No puedo recrear el "presente". Trabajo en torno a que lo mencionas.)

Una solución razonable es cambio del método de acceso de privada a protegidas para dar acceso a la constante de enumeración " subclases ".

Mejor sugerencia de título de pregunta: "Java private enum method?" o simplemente "Método privado de enumeración" (deje que la etiqueta Java se ocupe de Java-ness)

Cuestiones relacionadas