Подтвердить что ты не робот

Стационарный порядок инициализации Java

Я пытаюсь обнаружить порядок, в котором происходит инициализация, или, скорее, причина, почему происходит инициализация в этом порядке. С учетом кода:

public class Main {

    {
        System.out.printf("NON-STATIC BLOCK\n");
    }

    static{
        System.out.printf("STATIC BLOCK\n");
    }

    public static Main m = new Main();

    public Main(){
        System.out.printf("MAIN CONSTRUCTOR\n");
    }

    public static void main(String... args) {
        //Main m = new Main();
        System.out.printf("MAIN METHOD\n");

    }
}

Вывод:

STATIC BLOCK

NON-STATIC BLOCK

MAIN CONSTRUCTOR

MAIN METHOD

Однако перемещение объявления m перед созданием блока инициализации:

NON-STATIC BLOCK

MAIN CONSTRUCTOR

STATIC BLOCK

MAIN METHOD

и я совершенно не знаю, почему это происходит в этом порядке. Кроме того, если я исключаю ключевое слово static в объявлении m, ни блок init, ни огонь конструктора. Может ли кто-нибудь помочь мне с этим?

4b9b3361

Ответ 1

Я думаю, что вы просто отсутствуете раздел 12.4.2 JLS, который включает в себя:

Затем выполните либо инициализаторы переменной класса, и инициализаторы статического класса, или инициализаторы полей интерфейса, в текстовом порядке, как если бы они были одним блоком.

Часть "в текстовом порядке" является важным битом.

Если вы измените m как статическую переменную на переменную экземпляра, тогда поле не будет инициализировано инициализацией класса - оно будет инициализироваться только инициализацией экземпляра (т.е. при создании экземпляра). На данный момент это вызовет переполнение стека - для создания одного экземпляра требуется создать другой экземпляр, который требует создания другого экземпляра и т.д.

EDIT: аналогично раздел 12.5 указывает инициализацию экземпляра, включая следующие шаги:

  • Выполните инициализаторы экземпляра и инициализаторы переменных экземпляра для этого класса, присваивая значения инициализаторов переменной экземпляра соответствующим переменным экземпляра в порядке слева направо, в котором они отображаются в текстовом виде в исходном коде для класс. Если выполнение любого из этих инициализаторов приводит к исключению, то никакие новые инициализаторы не обрабатываются, и эта процедура завершается внезапно с тем же исключением. В противном случае перейдите к шагу 5.

  • Выполните оставшуюся часть тела этого конструктора. Если это выполнение завершается внезапно, то эта процедура завершается внезапно по той же причине. В противном случае эта процедура выполняется нормально.

Итак, почему вы видите "НЕСТАТИЧЕСКИЙ БЛОК" до "ГЛАВНОГО КОНСТРУКТОРА".