Статический порядок инициализации 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, ни огонь конструктора. Может ли кто-нибудь помочь мне с этим?

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

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

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

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

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

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

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

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

  • Как увидеть JavaDoc в IntelliJ IDEA?
  • Вычисление угла между линией, определяемой двумя точками
  • Android FragmentManager BackStackRecord.run бросает NullPointerException
  • Как получить список установленных принтеров?
  • В чем разница между @ + id / android: list и @ + id / list
  • Android Eclipse - Не удалось найти * .apk
  • Отладка Android InetAddress.isReachable
  • Android: невозможно найти явный class активности ... startActivity from the PreferenceActivity
  • Ошибка: class X является общедоступным, должен быть объявлен в файле с именем X.java
  • IDEA: javac: исходный релиз 1.7 требует целевого релиза 1.7
  • Как Java конвертирует int в байты?
  • Давайте будем гением компьютера.