2011-08-25 11 views
9

Me encontré con un error muy extraño y no puedo explicar por qué sucede. Imagine la siguiente enumeración:¿Por qué la inicialización de las constantes enum de Java no está completa?

import java.awt.Color; 

public class test { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     System.out.println(MyEnum.CONSTANT1.get()); 
     System.out.println(MyEnum.CONSTANT2.get()); 
    } 

    private enum MyEnum { 
     CONSTANT1(staticMethod1()), 
     CONSTANT2(staticMethod2()); 

     private static final Color WHY_AM_I_NULL = new Color(255, 255, 255); 

     private final Color color; 

     private MyEnum(Color color) { 
      this.color = color; 
     } 

     public Color get() { 
      return color; 
     } 

     private static Color staticMethod1() { 
      return new Color(100, 100, 100); 
     } 

     private static Color staticMethod2() { 
      return WHY_AM_I_NULL; 
     } 
    } 

} 

Los resultados cuando se ejecuta este son:

java.awt.Color[r=100,g=100,b=100] 
null 

La pregunta es, ¿por qué el segundo es nulo?

enmienda: Si ponemos la WHY_AM_I_NULL en una clase estática privada dentro de la enumeración, a continuación, se inicializa en primer lugar.

+0

Ammended nueva observación –

+1

Además, si intenta usar la constante directamente, no a través de un método, Eclipse muestra un error. Ese no es el caso cuando se usa el método estático. ¡Incluso FindBugs no muestra un problema! Creo que esto merece una advertencia al menos –

Respuesta

12

El problema es que todos los campos estáticos (y las instancias enum cuentan como tales) se inicializan en su orden declarado (specification). Por lo tanto, cuando se crea una instancia de CONSTANT2, el campo WHY_AM_I_NULL aún no se ha inicializado (y por lo tanto null).

Como no puede colocar el campo antes de las instancias enum, debe buscar otra forma de hacer lo que desee (por ejemplo, colocar el campo fuera de la clase enum). Si nos dices, lo que realmente quieres lograr, uno podría hacer más sugerencias.

Editar:WHY_AM_I_NULL Si pones en una clase anidada, los campos de esta clase se pueden inicializar en cuanto se accede por primera vez a la clase (es decir, en este caso durante la ejecución de staticMethod2).

+0

Solo quiero tener una constante, que se usa en la inicialización de la constante enum. Funcionó cuando puse la constante en una clase estática privada dentro de la enumeración. Los usuarios de este Enum no se preocupan por esta constante interna y no quiero que se declare más de una vez (o se crea más de una vez si lo tiene como método que crea el color) –

+1

En este caso De hecho, utilizaría una clase anidada estática como clase de titular de campo. –

4

Los enumeraciones son la característica del compilador. En realidad, el compilador crea una clase llamada MyEnum que contiene 2 campos estáticos públicos CONSTANT1 y CONSTANT2 y otro código.

La inicialización estática se realiza de arriba hacia abajo, por lo que se crea el CONSTANT2 y se inicializa antes de la variable estática WHY_AM_I_NULL. Es por eso que WHY_AM_I_NULL es nulo cuando CONSTANT2 se está inicializando.

1

Esto se debe a que los campos estáticos (incluidos los valores enum) se inicializan en el orden en que aparecen en el archivo.

Así CONSTANT1 y CONSTANT2 que éste se inicia antes de WHY_AM_I_NULL, por lo tanto, CONSTANT2 se inicializa con null.

2

WHY_AM_I_NULL es nula cuando staticMethod2 se invoca - esta es la forma JLS especifica inicialización

En una secuencia diferente se obtendría 100, 255 en lugar de 100, null:

private static final Color WHY_AM_I_NULL = new Color(255, 255, 255); 
private enum MyEnum { 
    CONSTANT1(staticMethod1()), 
    CONSTANT2(staticMethod2()); 
    //... 
+0

-1. Ni siquiera responde por qué un campo no se inicializa dentro de enum sino que desvía el problema mostrando cómo funciona fuera de enum. Otro punto a tener en cuenta es que ** nunca es una respuesta correcta escribir "Sucede porque así fue como se especificó". ** Ver [Cómo responder] (http://softwareengineering.stackexchange.com/help/how-to- responder) –

Cuestiones relacionadas