Порядок инициализации в Java, конструктор внутри статического блока - PullRequest
0 голосов
/ 02 марта 2019

Учитывая стандартные правила порядка инициализации Java, мне не ясно, почему следующий код

public class Foo {

    static { new Foo(); }

    static{ System.out.println("static code"); }

    { System.out.println("non static code"); }

    public Foo() { System.out.println("constructor"); }

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

выводит это:

non static code
constructor
static code

Ответы [ 3 ]

0 голосов
/ 02 марта 2019

Итак, статический блок будет выполнен, как только загрузчик класса загрузит класс.Итак, ваш первый статический блок static { new Foo(); } выполняется первым, что дополнительно вызывает конструктор new Foo();.Согласно java docs нестатический блок будет скопирован в каждый конструктор компилятором , что означает, что System.out.println("non static code"); будет скопирован в конструктор public Foo() { System.out.println("constructor"); }.Таким образом, сначала будет напечатано non static code, затем constructor.После выполнения первого статического блока он выполнит второй статический блок, который печатает последний static code.

После компиляции ваш код выглядит примерно так, как показано ниже:

public class Foo {

    static { new Foo(); }

    static{ System.out.println("static code"); }

    public Foo() { 
       System.out.println("non static code");
       System.out.println("constructor"); 
    }

    public static void main(String[] args) {}
}
0 голосов
/ 02 марта 2019

JLS сообщает, что

  • Статические блоки и инициализация статических переменных будут выполняться в порядке исходного кода программы при инициализации класса.

  • Блоки экземпляра и инициализация переменных экземпляра будут выполняться в порядке исходного кода программы при инициализации экземпляра.Это происходит после инициализации супер экземпляра и до выполнения тела конструктора.

В вашем примере первый статический создает экземпляр Foo.Это вызывает выполнение экземпляра блока для Foo , в то время как выполняется первый статический блок.Итак, последовательность:

  1. Класс загружен
  2. Статическая инициализация для Foo запущена
  3. Выполняется первый статический блок, который выполняет new Foo().
    1. Выполнен блок экземпляра - печатается «нестатический код»
    2. Выполнен конструктор - печатается «конструктор»
  4. Завершается первый статический блок.
  5. Выполняется второй статический блок - печатается «статический код».
  6. Вызывается основной метод.
0 голосов
/ 02 марта 2019

Что ж, для рефакторинга кода выполните следующие шаги:

1) удалите нестатический блок инициализации - компилятор помещает его перед кодом в фактическом конструкторе

public class Foo {

    static { new Foo(); }

    static{ System.out.println("static code"); }

    public Foo() {
        System.out.println("non static code");
        System.out.println("constructor");
     }

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

2) Соединить блоки статической инициализации - см. здесь :

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

public class Foo {

    static {
        new Foo();
        System.out.println("static code");
     }

    public Foo() {
        System.out.println("non static code");
        System.out.println("constructor");
     }

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

3) Оттуда это должно быть очевидно.

...