Вы должны знать, что
- первая инструкция в конструкторе вызывает конструктор его родительского класса
super(params)
или если вы хотите использовать конструктор по умолчанию super()
. В случае конструктора по умолчанию вам не нужно писать его явно.
- код в блоке инициализатора перемещается в каждый конструктор сразу после вызова
super(...)
- статический блок выполняется, когда класс инициализируется, что выполняется после его полной загрузки (с его родительскими классами) JVM.
Итак, классы компилируются в классы, подобные этому.
public class Parent {
static {
System.out.println("Parent static block");
}
public Parent() {
super();
{
System.out.println("Parent initializer block");
}
System.out.println("Parent constructor");
}
}
public class Son extends Parent {
static {
System.out.println("Son static block");
}
public Son() {
super();
{
System.out.println("Son initializer block");
}
System.out.println("Son constructor");
}
public static void main(String[] args) {
new Son();
}
}
Чтобы иметь возможность выполнять метод main
из класса Son
, JVM необходимо загрузить код этого класса (и классов, которые он расширяет). После полной загрузки класса JVM инициализирует его статическое содержимое, которое включает выполнение статических блоков (да, в одном классе может быть более одного статического блока). Для полной загрузки Son
класса JVM необходимо знать подробности о своем родительском классе, чтобы он полностью загрузил Parent
класс до Son
, что означает, что он также будет выполнять свои статические блоки перед статическими блоками в классе Son
.
Таким образом, результат будет выглядеть так:
Parent static block
Son static block
Теперь в методе main
вы вызываете конструктор класса Son
через new Son()
, код которого выглядит как
super();
{
System.out.println("Son initializer block");
}
System.out.println("Son constructor");
Поскольку его super()
относятся к конструктору класса Parent
, который
super();// this will invoke Object constructor since Parent
// doesn't extend anything (which means it extends Object class)
{
System.out.println("Parent initializer block");
}
System.out.println("Parent constructor");
в результате вы увидите
Parent initializer block
Parent constructor
Это обрабатывает Parent#constructor()
, выполняемое с super()
, поэтому теперь вы увидите код из конструктора Son после super()
, который сгенерирует
Son initializer block
Son constructor
Чтобы увидеть, что классы будут загружены еще до того, как вы используете Son
конструктор или даже main
метод, вы можете просто распечатать что-нибудь перед использованием Son
конструктора, например
System.out.println("ABC // before new Son()");
new Son();
что приведет к
Parent static block
Son static block
ABC // before new Son()
Parent initializer block
Parent constructor
Son initializer block
Son constructor
person
Pshemo
schedule
01.02.2014