tutorial interfaz grafica español ejemplos componentes java enums

java - interfaz - ¿Por qué las implementaciones de enumeración no pueden acceder a campos privados en la clase de enumeración?



jframe en java (4)

Acabo de responder a esta pregunta diciendo cómo resolver el problema de compilación:

¿Cómo usar los campos en enumeración de java anulando el método?

Pero lo que no entiendo es por qué el error está ocurriendo en primer lugar.

Aquí está el ejemplo escrito como una enumeración:

public enum MyEnum { FIRST { @Override public String doIt() { return "1: " + someField; //error } }, SECOND { @Override public String doIt() { return "2: " + super.someField; //no error } }; private String someField; public abstract String doIt(); }

Aquí es exactamente lo mismo que las clases abstractas

abstract class MyClass { class FIRST extends MyClass { @Override public String doIt() { return "1: " + someField; //no error } }; class SECOND extends MyClass { @Override public String doIt() { return "2: " + super.someField; //no error } }; private String someField; public abstract String doIt(); }

En el caso de FIRST dentro de la implementación de la enum , no puede acceder a someField . Sin embargo, en el caso de la clase abstracta puede.

Además, agregar super arreglos al problema, al igual que quitar el modificador private en el campo.

¿Alguien sabe por qué esta ligera peculiaridad en el comportamiento está sucediendo?


Cuando se resuelve un identificador, Java prefiere el ámbito léxico sobre los miembros heredados. Entonces, cuando tiene una clase interna que extiende la clase externa y usa un campo de la clase externa sin usar this o super , se accede al campo de la instancia externa, que falla si la clase interna es static ya que no hay instancia externa. Por el contrario, cuando usa super , está accediendo explícitamente al miembro heredado. Tenga en cuenta que las clases enum son implícitamente static Incluso puede usar this para acceder al miembro heredado, pero tiene que usar ((MyClass)this).someField para acceder si se declara private .


La clase FIRST es una clase interna de MyClass y también una subclase. La razón por la que no ve un error al acceder a someField es porque está accediendo al campo someField de la clase externa, no a la súper clase.

class MyClass { class FIRST extends MyClass { @Override public String doIt() { super.someField = "super"; return "1: " + someField; } }; private String someField = "outer"; public String doIt(){return "";} public static void main(String[] args) { System.out.println(new MyClass().new FIRST().doIt()); } }

Impresiones 1: outer .

En el otro caso, sus constantes de enumeración se comportan como subclases anidadas estáticas, no como clases internas, por lo que no tienen una referencia a la clase externa, solo su súper clase.


No estoy de acuerdo con la respuesta aceptada.

La declaración de enum const es public static final implícita, pero no la clase a la que pertenece enum const.

Del Capítulo JSL 8. Clases

El cuerpo de clase opcional de una constante de enumeración define implícitamente una declaración de clase anónima (§15.9.5) que extiende el tipo de enumeración que lo encierra de inmediato. El cuerpo de la clase se rige por las reglas habituales de las clases anónimas.

¿Y cuáles son las ''reglas de las clases anónimas''?

Del Capítulo 15 de JSL:

El compilador de Java deriva automáticamente una declaración de clase anónima de una expresión de creación de instancia de clase.

Una clase anónima nunca es abstracta (§8.1.1.1).

Una clase anónima siempre es implícitamente final (§8.1.1.2).

Una clase anónima es siempre una clase interna (§8.1.3); nunca es estático (§8.1.1, §8.5.1).

Y si la clase equivalente enum es una clase estática, ¿cómo explicar el siguiente error?

public enum MyClass { First { public static int b; //(2)Illegal static declaration in inner class }; }

Pero, ¿por qué una clase interna no puede acceder al campo de la clase externa?

Una posible clase equivalente de enumeración puede verse como la siguiente, lo que da el mismo error que una clase de enumeración:

abstract class MyClass { private int someField; static { class First extends MyClass { public void method() { System.out.println(someField); } private static int b; } } }

Más:


Su clase abstracta no es equivalente a su enumeración, ya que las enumeraciones son implícitamente públicas final estática. Por lo tanto, observarás el mismo comportamiento si usas:

abstract class MyClass { static class FIRST extends MyClass { @Override public String doIt() { return "1: " + someField; // error } }; static class SECOND extends MyClass { @Override public String doIt() { return "2: " + super.someField; // no error } }; private String someField; public abstract String doIt(); }

Como se explica en http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html , capítulo "Clases anidadas estáticas":

Una clase anidada estática no puede referirse directamente a las variables de instancia o métodos definidos en su clase adjunta: puede usarlas solo a través de una referencia de objeto.

De ahí la necesidad de super . También puede usar this si el campo estuviera protected lugar de private .