Ха, смешно!Всего несколько дней назад я наткнулся на это.
Из спецификации языка Java, третье издание, раздел 8.9:
Ссылка на ошибку во время компиляциистатическое поле типа enum, которое не является константой времени компиляции (§15.28) из конструкторов, блоков инициализатора экземпляра или выражений инициализатора переменной экземпляра этого типа.Это ошибка времени компиляции, когда конструкторы, блоки инициализатора экземпляра или выражения инициализатора переменной экземпляра константы перечисления e ссылаются на себя или на константу перечисления того же типа, которая объявлена справа от e.
Обсуждение
Без этого правила очевидно разумный код не будет работать во время выполнения из-за цикличности инициализации, присущей типам enum.(В любом классе с «самоподписанным» статическим полем существует цикличность.) Вот пример кода, который потерпит неудачу:
enum Color {
RED, GREEN, BLUE;
static final Map<String,Color> colorMap =
new HashMap<String,Color>();
Color() {
colorMap.put(toString(), this);
}
}
Статическая инициализация этого типа перечисления будетбросить NullPointerException, потому что статическая переменная colorMap неинициализируется при запуске конструкторов для констант перечисления.Приведенное выше ограничение гарантирует, что такой код не будет компилироваться.
Обратите внимание, что пример может быть легко реорганизован для правильной работы:
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);
}
}
Реорганизованная версия явно верна, так какстатическая инициализация происходит сверху вниз.