我找到这个例子,我想了解它背后的逻辑?构造函数和静态块以及初始化程序块如何在继承中工作?在哪个阶段被称为?
public class Parent { static { System.out.println("i am Parent 3"); } { System.out.println("i am parent 2"); } public Parent() { System.out.println("i am parent 1"); } } public class Son extends Parent { static {System.out.println("i am son 3");} {System.out.println("i am son 2");} public Son() { System.out.println("i am son 1"); } public static void main(String[] args) { new Son(); } }
输出是:
i am Parent 3 i am son 3 i am parent 2 i am parent 1 i am son 2 i am son 1
Pshemo.. 11
你需要知道这一点
构造函数中的第一条指令是调用其父类的构造函数,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
JB Nizet.. 9
当类由JVM加载并初始化时,会调用一次静态块.在构造类的实例时执行实例初始化程序,就像构造函数一样.
静态和实例初始值设定项在Java语言规范中描述
你需要知道这一点
构造函数中的第一条指令是调用其父类的构造函数,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
当类由JVM加载并初始化时,会调用一次静态块.在构造类的实例时执行实例初始化程序,就像构造函数一样.
静态和实例初始值设定项在Java语言规范中描述