Скажите, что проект содержит несколько классов, каждый из которых имеет статический блок инициализатора. В каком порядке работают те блоки? Я знаю, что в классе, такие блоки выполняются в порядке, они появляются в коде. Я считал, что это - то же через классы, но некоторый код кода, который я написал, не соглашается с этим. Я использовал этот код:
package pkg;
public class LoadTest {
public static void main(String[] args) {
System.out.println("START");
new Child();
System.out.println("END");
}
}
class Parent extends Grandparent {
// Instance init block
{
System.out.println("instance - parent");
}
// Constructor
public Parent() {
System.out.println("constructor - parent");
}
// Static init block
static {
System.out.println("static - parent");
}
}
class Grandparent {
// Static init block
static {
System.out.println("static - grandparent");
}
// Instance init block
{
System.out.println("instance - grandparent");
}
// Constructor
public Grandparent() {
System.out.println("constructor - grandparent");
}
}
class Child extends Parent {
// Constructor
public Child() {
System.out.println("constructor - child");
}
// Static init block
static {
System.out.println("static - child");
}
// Instance init block
{
System.out.println("instance - child");
}
}
и получил этот вывод:
ЗАПУСТИТЬ
статичный - прародитель
статичный - родитель
статичный - ребенок
экземпляр - прародитель
конструктор - прародитель
экземпляр - родитель
конструктор - родитель
экземпляр - ребенок
конструктор - ребенок
КОНЕЦ
Очевидный ответ от этого - то, что блоки родителей работают перед их детским, но это могло просто быть совпадением и не помогает, если два класса не находятся в той же иерархии.
Править:
Я изменил свой пример кода путем добавления этого к LoadTest.java:
class IAmAClassThatIsNeverUsed {
// Constructor
public IAmAClassThatIsNeverUsed() {
System.out.println("constructor - IAACTINU");
}
// Instance init block
{
System.out.println("instance - IAACTINU");
}
// Static init block
static {
System.out.println("static - IAACTINU");
}
}
Как подразумевается именем класса, я никогда не ссылался на новый класс нигде. Новая программа произвела тот же вывод как старый.
] Статический инициализатор для класса запускается при первом обращении к нему, либо для создания экземпляра, либо для доступа к статическому методу или полю [
]. [] Итак, для нескольких классов это полностью зависит от кода, который запускается, чтобы вызвать загрузку этих классов. [
]Смотрите раздел 12.4 и 12.5 JLS версии 8, они вдаются в кровавые подробности обо всем этом (12.4 для статических и 12.5 для, например, переменных).
Для статической инициализации (раздел 12.4):
Класс или тип интерфейса T будет инициализирован непосредственно перед первым появлением любого из следующих элементов:
(и несколько пунктов о слове ласка)
.ответы Кита и Криса великолепны, я просто добавляю некоторые подробности к моему конкретному вопросу.
Статические блоки init выполняются в том порядке, в котором инициализируются их классы. Итак, какой это порядок? В JLS 12.4.1:
Класс или тип интерфейса T инициализируется непосредственно перед первым появлением любого из следующих элементов:
- T - это класс и создается экземпляр T.
- T является классом, и вызывается статический метод, объявленный T.
- Присваивается статическое поле, объявленное T.
- Используется статическое поле, объявленное T, и это поле не является константной переменной (§4.12.4).
- T является классом верхнего уровня, и выполняется утверждение утверждения (§14.10), лексически вложенное в T.
Вызов определенных отражающих методов в классе и в пакете java.lang.reflect также вызывает инициализацию класса или интерфейса. Класс или интерфейс не инициализируется ни при каких других обстоятельствах.
Для иллюстрации приведен обзор того, что происходит в данном примере: