Пример кода, который утвержден в качестве ответа, является правильным, но я не согласен с ним.Он не показывает, что происходит, и я собираюсь показать вам хороший пример, чтобы понять, как на самом деле работает JVM:
package test;
class A {
A() {
print();
}
void print() {
System.out.println("A");
}
}
class B extends A {
static int staticVariable2 = 123456;
static int staticVariable;
static
{
System.out.println(staticVariable2);
System.out.println("Static Initialization block");
staticVariable = Math.round(3.5f);
}
int instanceVariable;
{
System.out.println("Initialization block");
instanceVariable = Math.round(3.5f);
staticVariable = Math.round(3.5f);
}
B() {
System.out.println("Constructor");
}
public static void main(String[] args) {
A a = new B();
a.print();
System.out.println("main");
}
void print() {
System.out.println(instanceVariable);
}
static void somethingElse() {
System.out.println("Static method");
}
}
Прежде чем начать комментировать исходный код, я дам вамкраткое объяснение статических переменных класса:
Во-первых, они называются переменными класса, они принадлежат классу, а не конкретному экземпляру класса.Все экземпляры класса совместно используют эту статическую (классовую) переменную.Каждая переменная имеет значение по умолчанию в зависимости от примитива или ссылочного типа.Другое дело, когда вы переназначаете статическую переменную в некоторых членах класса (блоки инициализации, конструкторы, методы, свойства) и, делая это, вы изменяете значение статической переменной не для конкретного экземпляра, вы меняете его для всехэкземпляров.В заключение о статической части я скажу, что статические переменные класса создаются не тогда, когда вы впервые создаете экземпляр класса, они создаются при определении класса, они существуют в JVM без необходимости каких-либо экземпляров.Поэтому правильный доступ к статическим членам из внешнего класса (класс, в котором они не определены) заключается в использовании имени класса, следующего за точкой, а затем статического члена, к которому вы хотите получить доступ (шаблон: <CLASS_NAME>.<STATIC_VARIABLE_NAME>
).
Теперь давайте посмотрим на код выше:
Точка входа является основным методом - всего три строки кода.Я хочу сослаться на пример, который в настоящее время одобрен.В соответствии с этим первое, что должно быть напечатано после печати «Статического блока инициализации», это «Блок инициализации», и вот мое несогласие, нестатический блок инициализации не вызывается перед конструктором, он вызывается перед любой инициализацией конструкторов.класса, в котором определен блок инициализации.Конструктор класса - это первое, что задействуется при создании объекта (экземпляра класса), а затем при вводе конструктора первая вызываемая часть является либо неявным (по умолчанию) супер-конструктором, либо явным супер-конструктором, либо явным вызовом другого перегруженногоконструктор (но в какой-то момент, если есть цепочка перегруженных конструкторов, последний вызывает супер-конструктор, неявно или явно).
Существует полиморфное создание объекта, но прежде чем войти в класс B и его основной метод, JVM инициализирует все переменные класса (статические), затем проходит через статические блоки инициализации, если таковые существуют, и затем вводиткласс B и начинается с выполнения основного метода.Он переходит к конструктору класса B, а затем немедленно (неявно) вызывает конструктор класса A, используя полиморфизм, метод (переопределенный метод), вызываемый в теле конструктора класса A, который определен в классе B, и в этом случаепеременная с именем instanceVariable используется перед повторной инициализацией.После закрытия конструктора класса B поток возвращается конструктору класса B, но перед печатью «Конструктора» он идет сначала в нестатический блок инициализации.Для лучшего понимания отладки с помощью некоторой IDE, я предпочитаю Eclipse.