Блоки инициализации. Порядок выполнения в enum

Блоки инициализации. Порядок выполнения в enum

Для enum-классов сначала вызываются попарно динамический блок инициализации и конструктор, и только потом статические блоки инициализации.

Определение enum-класса начинается с его констант, которые инициализируются в статическом блоке инициализации, вызывая свой приватный конструктор.
Поскольку статические блоки инициализации выполняются в порядке их появления в коде, то любой статический блок, добавленный в описание enum-класса, выполнится после того, как будут созданы константы класса. Это хорошо видно, если декомпилировать байт-код enum-класса.

Исходный класс:


enum Level {
    BEGINNER, EXPERT;
}
Декомпелированный байт-код:


final class Level extends Enum
{
    public static final Level BEGINNER;
    public static final Level EXPERT;
    private static final Level $VALUES[];

    static {
        BEGINNER = new Level("BEGINNER", 0);
        EXPERT = new Level("EXPERT", 1);
        $VALUES = (new Level[]{
            BEGINNER, EXPERT
        });
    }

    private Level(String s, int i) {
          super(s, i);
    }

    // остальной код
}
Тогда для такой реализации класса:


enum Level {
    BEGINNER, EXPERT;

    static {
        System.out.println("Static block");
    }

    {
        System.out.println("Init block");
    }

    Level() {
        System.out.println("Constructor");
    }
}
При загрузке его в память вывод будет такой:


/*
Init block
Constructor
Init block
Constructor
Static block
*/
Для каждой константы попарно вызвался динамический блок инициализации (выполняется перед конструктором) и конструктор, а статический блок - только один раз и только после всех вызовов конструктора.
Методы и Инкапсуляция