Внутри класса очередность инициализации определяется порядком следования переменных, объявленных в этом классе. Определения переменных могут быть разбросаны по разным определениям методов, но в любом случае переменные инициализируются перед вызовом любого метода — даже конструктора. Например:
w3 = new Window(33); // Повторная инициализация w3
}
Window w2 = new Window(2); // После конструктора
void f() { print("f()"); }
Window w3 = new Window(3); // В конце
}
public class OrderOfInitialization {
public static void main(String[] args) {
House h = new House();
h.f(); // Показывает, что объект сконструирован
}
}
<spoiler text="Output:">
Window(1)
Window(2)
Window(3)
House()
Window(33)
f()
</spoiler> В классе House определения объектов Window намеренно разбросаны, чтобы доказать, что все они инициализируются перед выполнением конструктора или каким-то другим действием. Вдобавок ссылка w3 заново проходит инициализацию в конструкторе.
Из результатов программы видно, что ссылка w3 минует двойную инициализацию, перед вызовом конструктора и во время него. (Первый объект теряется, и со временем его уничтожит сборщик мусора.) Поначалу это может показаться неэффективным, но такой подход гарантирует верную инициализацию — что произошло бы, если бы в классе был определен перегруженный конструктор, который не инициализировал бы ссылку w3, а она при этом не получала бы значения по умолчанию?