Создание объекта класса в его собственном статическом инициализаторе
По JLS:
Класс или тип интерфейса T будет инициализирован непосредственно перед первое вхождение любого из следующего:
T - это класс и создается экземпляр T.
Также он говорит,
Инициализация класса состоит из выполнения его статического инициализаторы и инициализаторы для статических полей (переменные класса) объявленный в классе
Я выложу две точки из этого
- Инициализация классов состоит из выполнения статических инициализаторов
- Инициализация класса происходит, если класс создан.
Теперь,
Я предполагаю, что когда я создаю объект класса Test в своем собственном (Test own) статическом инициализаторе, он должен бросать мне переполнение стека, так как он должен вызывать себя повторно, потому что в соответствии с вышеприведенными двумя точками инициализация класса должна инициализироваться класс и блок инициализации имеют экземпляр класса. Переполнение стека происходит, когда я создаю экземпляр класса в своем собственном конструкторе или в его собственных инициализаторах экземпляра.
Например,
public class Test {
static{
System.out.println("static test");
new Test();
}
{
//new Test(); // This will give a stack overflow
System.out.println("intializer");
}
public Test(){
//new Test(); // This will give a stack overflow
System.out.println("constructor");
}
public static void main(String[] args) {
}
}
Однако результат - это нечто иное.
Результат:
статический тест intializer Конструктор
Либо я слишком запутался в понимании инициализации класса, либо я извиняюсь, если мне не хватает чего-то очень очевидного здесь и ценю вашу помощь.
Ответы
Ответ 1
Шаг 3 процедуры инициализации класса, указанный в разделе JLS 12.4.2,
Если объект класса для C указывает, что инициализация выполняется для C текущим потоком, то это должно быть рекурсивным запросом на инициализацию. Отпустите LC и завершите работу нормально.
Создание экземпляра класса в его статическом инициализаторе не рекурсивно повторно инициализирует класс; рекурсивные запросы на инициализацию обнаружены и ничего не делают.
(Обратите внимание, что "закончить нормально" означает "операция выполнена", а не "следовать шагам, которые обычно выполняются для завершения операции", это противоположно "завершается внезапно", что означает, что мы получили какую-то исключение или ошибка.)
Ответ 2
Статический инициализатор вызывается только при загрузке класса. Игнорирование объекта в статическом инициализаторе не приведет к тому, что снова будет загружен класс, загрузка класса происходит только один раз, загрузчик классов кэширует класс для жизни экземпляра JVM.
Если вы создали новый экземпляр в инициализаторе экземпляра или в конструкторе, вы получите ошибку stackoverflow.