Одноэлементный шаблон выполняет проблему заказа

Я пытаюсь изучить шаблон одноэлементного дизайна. Код выглядит следующим образом:

public class Model {

    private static final Model INSTANCE = new Model();

    public static void main(String[] args) {
        Model.getInstance();
    }

    private Model(){
        System.out.println("constructor");
    }

    public static Model getInstance(){

        System.out.println("I hope to be printed first!");
        return INSTANCE;
   }
}

Я ожидаю, что код сначала напечатает I hope to be printed first!, а затем пройдет через конструктор класса. но вывод кода обратный:

constructor
I hope to be printed first!

Я не могу понять, почему класс создается первым?


person alex    schedule 27.01.2020    source источник
comment
Статические поля инициализируются сразу после загрузки класса. Вам нужно INSTANCE лениво инициализировать.   -  person Sweeper    schedule 27.01.2020
comment
@Sweeper, вы имеете в виду, что класс был загружен при запуске main перед выполнением getInstance()?   -  person alex    schedule 27.01.2020
comment
Может быть, это помогает? stackoverflow.com/questions/8297705 /   -  person jrook    schedule 27.01.2020
comment
@jrook спасибо за ценную ссылку. Я не ищу обходной путь сейчас. мне нужно знать что происходит в коде   -  person alex    schedule 27.01.2020


Ответы (2)


Еще до выполнения метода main() загрузчик классов JVM загружает класс в память. В это время он инициализирует все статические переменные и выполняет статические блоки инициализации в том порядке, в котором они появляются в классе (сверху вниз).

Итак, поскольку ваша переменная INSTANCE является статической, ее необходимо инициализировать. Итак, конструктор вызывается для создания экземпляра класса Model, чтобы затем присвоить его переменной INSTANCE. Поскольку это единственная статическая переменная и статических блоков инициализации нет, то выполняется метод main, который вызывает Model.getInstance().

При написании кода, который инициализирует различные типы полей, конечно, мы должны следить за порядком инициализации.

В Java порядок операторов инициализации следующий:

статические переменные и статические инициализаторы по порядку

переменные экземпляра и инициализаторы экземпляра по порядку

конструкторы

https://www.baeldung.com/java-initialization

person Ivan    schedule 27.01.2020

Статические переменные инициализируются при загрузке класса. Они инициализируются перед созданием любого объекта этого класса. Поскольку статические переменные инициализируются до выполнения любого статического метода класса, вы получаете ожидаемый результат. Проверьте https://beginnersbook.com/2013/05/static-variable/. и https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html для получения более подробной информации и некоторых примеров.

person Arvind Kumar Avinash    schedule 27.01.2020