Порядок инициализации полей в классе

#java

#java

Вопрос:

Я пытаюсь понять порядок области видимости Java.

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

У меня есть приведенный ниже код:

 public class A {
    private int x;

    {
        System.out.println(x);
    }

    {
        x = 1;
    }
    
    public A() {
    }

    public static void main(String[] args) {
        new A();
    }

}
  

который успешно компилируется, затем я попытался поменять местами несколько фрагментов кода:

 public class A {

    {
        x = 1;
    }

    {
        System.out.println(x);
    }

    private int x;


    public A() {
    }

    public static void main(String[] args) {
        new A();
    }

}
  

и Java не может скомпилировать его в строку:

    System.out.println(x);
  

с Illegal forward reference

Я не понимаю, почему Java успешно обрабатывает строку

 x = 1;
  

во втором примере.
НО это успешно работает, если строка с печатью заменяется на

    System.out.println(this.x);
  

Комментарии:

1. Это всего лишь один из тех случаев, когда «так оно и есть». Прочитайте все об этом в спецификации языка Java в 8.3.3. Пересылать ссылки во время инициализации полей

2. Ограничения на ссылки на поля в инициализаторах docs.oracle.com/javase/specs/jls/se14/html/jls-8.html#jls-8.3.3