Hah, drôle! Il y a quelques jours, j'ai trébuché sur ça.
De la spécification du langage Java, troisième édition, Section 8.9:
Il est une erreur de compilation pour faire référence à un champ statique d'un type ENUM qui n'est pas une constante de compilation (§15.28) à partir de constructeurs, de blocs d'initialisation d'instance ou d'expressions d'initialisation de variable d'instance de ce type. Il s'agit d'une erreur de compilation pour les constructeurs, les blocs d'initialisation d'instance ou les expressions d'initialisation de variable d'instance d'une constante enum e pour se référer à elle ou à une constante enum du même type déclarée à droite de e.
Discussion
Sans cette règle, le code semble raisonnable échouer au moment de l'exécution en raison de l'initialisation tautologique types enum. (A circularité existe dans une classe avec un « auto typé » champ statique.) Voici un exemple du genre de code qui échouerait:
enum Color {
RED, GREEN, BLUE;
static final Map<String,Color> colorMap =
new HashMap<String,Color>();
Color() {
colorMap.put(toString(), this);
}
}
initialisation statique de ce type ENUM une NullPointerException car la variable statique colorMap n'est pas initialisée lorsque les constructeurs des constantes enum s'exécutent. La restriction ci-dessus garantit que ce code ne compilera pas.
Notez que l'exemple peut facilement être refactorisé pour fonctionner correctement:
enum Color {
RED, GREEN, BLUE;
static final Map<String,Color> colorMap =
new HashMap<String,Color>();
static {
for (Color c : Color.values())
colorMap.put(c.toString(), c);
}
}
La version remaniée est clairement correcte, que l'initialisation statique se produit haut en bas.
Il peut être utile de préciser si la 'clé' pour la carte est toujours le 'nom' de l'énumération. Si c'est le cas, cela fait une grande différence dans la façon dont vous feriez cela. – DJClayworth