Мы можем поместить код в конструктор, метод или блок инициализации. Для чего нужен блок инициализации? Обязательно ли, чтобы он был в каждой программе Java?
Этот код должен иллюстрировать их использование и в каком порядке они выполняются:
publicclassTest {
staticint staticVariable; int nonStaticVariable;
// Static initialization block: // Runs once (when the class is initialized) static { System.out.println("Static initalization."); staticVariable = 5; }
// Instance initialization block: // Runs each time you instantiate an object { System.out.println("Instance initialization."); nonStaticVariable = 7; }
Блоки инициализации экземпляра полезны, если вы хотите, чтобы некоторый код выполнялся независимо от того, какой конструктор используется, или если вы хотите выполнить некоторую инициализацию экземпляра для анонимных классов.
Ответ 2
хотел бы добавить к ответу @aioobe
Порядок выполнения:
статические блоки инициализации суперклассов
статические блоки инициализации класса
блоки инициализации экземпляров суперклассов
конструкторы суперклассов
блоки инициализации экземпляра класса
конструктор класса.
Следует иметь в виду пару дополнительных моментов (пункт 1 является повторением ответа @aioobe):
Код в блоке статической инициализации будет выполняться во время загрузки класса (и да, это означает, что только один раз за загрузку класса), перед созданием любых экземпляров класса и перед вызовом любых статических методов.
Блок инициализации экземпляра фактически копируется компилятором Java в каждый конструктор, который есть в классе. Таким образом, каждый раз код в блоке инициализации экземпляра выполняется точно перед кодом в конструкторе.
Ответ 3
хороший ответ от aioobe, добавляющий еще несколько моментов
это похоже на констатацию очевидного, но кажется немного более понятным.
Ответ 4
Пример кода, который утвержден здесь в качестве ответа, правильный, но я с ним не согласен. Он не показывает, что происходит, и я собираюсь показать вам хороший пример, чтобы понять, как на самом деле работает JVM:
Прежде чем начать комментировать исходный код, я дам вам краткое объяснение статических переменных класса:
Во-первых, они называются переменными класса, они принадлежат классу, а не конкретному экземпляру класса. Все экземпляры класса совместно используют эту статическую переменную (class). Каждая переменная имеет значение по умолчанию, в зависимости от примитивного или ссылочного типа. Другое дело, когда вы переназначаете статическую переменную в некоторых членах класса (блоках инициализации, конструкторах, методах, свойствах) и при этом вы изменяете значение статической переменной не для конкретного экземпляра, вы изменяете его для всех экземпляров. В заключение статической части я скажу, что статические переменные класса создаются не при первом создании экземпляра класса, они создаются при определении вашего класса, они существуют в JVM без необходимости в каких-либо экземплярах. Для правильного доступа к статическим элементам из внешнего класса (класса, в котором они не определены) используется имя класса, за которым следует точка, а затем статический элемент, к которому вы хотите получить доступ (шаблон: <CLASS_NAME>.<STATIC_VARIABLE_NAME>).
Теперь давайте посмотрим на приведенный выше код:
Точка входа - это основной метод - всего три строки кода. Я хочу сослаться на пример, который в настоящее время одобрен. Согласно этому первое, что должно быть напечатано после печати "Блока статической инициализации", - это "Блок инициализации", и вот мое несогласие, блок нестатической инициализации не вызывается перед конструктором, он вызывается перед любыми инициализациями конструкторов класса, в котором определен блок инициализации. Конструктор класса - это первое, что задействовано при создании объекта (экземпляра класса), а затем, когда вы вводите конструктор, первая вызываемая часть является либо неявным (по умолчанию) суперконструктором, либо явным суперконструктором, либо явным вызовом другого перегруженного конструктора (но в какой-то момент, если есть цепочка перегруженных конструкторов, последний вызывает суперконструктор, неявно или явно).
Происходит полиморфное создание объекта, но перед входом в класс B и его основной метод JVM инициализирует все переменные класса (статические), затем проходит через блоки статической инициализации, если таковые существуют, а затем входит в класс B и начинает выполнение основного метода. Он переходит к конструктору класса B, затем немедленно (неявно) вызывает конструктор класса A, используя полиморфизм метод (переопределенный метод), вызываемый в теле конструктора класса A, является тем, который определен в классе B, и в этом случае переменная с именем instanceVariable используется перед повторной инициализацией. После закрытия конструктора класса B поток возвращается к конструктору класса B, но сначала он переходит к блоку нестатической инициализации, прежде чем печатать "Конструктор". Для лучшего понимания отладки с помощью какой-либо IDE я предпочитаю Eclipse.