Java 继承中的静态块与初始值设定项块与构造函数
我找到了这个例子,我想了解它背后的逻辑?构造函数、静态块和初始值设定项块在继承中是如何工作的?在哪个阶段,每一个都被称为Java 继承中的静态块与初始值设定项块与构造函数,java,inheritance,constructor,polymorphism,static-block,Java,Inheritance,Constructor,Polymorphism,Static Block,我找到了这个例子,我想了解它背后的逻辑?构造函数、静态块和初始值设定项块在继承中是如何工作的?在哪个阶段,每一个都被称为 public class Parent { static { System.out.println("i am Parent 3"); } { System.out.println("i am parent 2"); } public Parent() { System.out.pr
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
当类被JVM加载和初始化时,静态块被调用一次。实例初始值设定项是在构造类的实例时执行的,就像构造函数一样
静态和实例初始值设定项在中描述,当JVM加载和初始化类时,静态块被调用一次。实例初始值设定项是在构造类的实例时执行的,就像构造函数一样
静态和实例初始值设定项在类加载到JVM时执行静态块,而构造函数块在创建实例时执行
静态初始值设定项相当于静态上下文中的构造函数。您肯定会看到,这比实例初始值设定项更常见。静态块在类加载到JVM时执行,而构造函数块在创建实例时执行
静态初始值设定项相当于静态上下文中的构造函数。您肯定会比实例初始值设定项更经常地看到这一点。当您的类被加载时,静态块被调用,并且您的类首先由jvm中的classloader加载,所以它们首先被执行
然后,您创建对象,以便调用父init块,然后由于java中的构造函数链接而调用父构造函数,然后在加载类时调用派生类init块,然后调用派生类构造函数 然后创建对象,这样就调用父init块,然后调用父构造函数,这是由于java中的构造函数链接,然后是派生类init块,然后是派生类构造函数
super(params)
,或者如果要使用默认构造函数super()
。对于默认构造函数,您不必显式地编写它super(…)
调用之后立即移动到每个构造函数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();
}
}
为了能够从Son
类执行main
方法,JVM需要加载此类(及其扩展的类)的代码。类完全加载后,JVM初始化其静态内容,这涉及到执行静态块(是的,一个类中可以有多个静态块)。要完全加载Son
类,JVM需要知道其父类的详细信息,以便在Son
类之前完全加载parent
类,这意味着它还将在Son
类中的静态块之前执行其静态块
因此,输出将如下所示:
父静态块
子静态块
main
方法中,通过new-Son()
调用Son
类构造函数
super();
{
System.out.println("Son initializer block");
}
System.out.println("Son constructor");
因为它的super()
引用了父类构造函数,它是
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");
结果你会看到
父初始值设定项块
父构造函数
这将处理使用super()
执行的Parent#constructor()
,因此接下来您将看到子构造函数在super()
之后生成的代码
子初始值设定项块
Son构造函数
要查看在使用Son
constructor或甚至main
方法之前是否会加载类,您可以在使用Son
constructor之前打印一些内容
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
你必须知道这一点
构造函数中的第一条指令是调用其父类的构造函数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();
}
}
为了能够从Son
类执行main
方法,JVM需要加载此类(及其扩展的类)的代码。类完全加载后,JVM初始化其静态内容,这涉及到执行静态块(是的,一个类中可以有多个静态块)。要完全加载Son
类,JVM需要知道其父类的详细信息,以便在Son
类之前完全加载parent
类,这意味着它还将在Son
类中的静态块之前执行其静态块
因此,输出将如下所示:
父静态块
子静态块
现在在main
方法中,通过new-Son()
调用Son
类构造函数
super();
{
System.out.println("Son initializer block");
}
System.out.println("Son constructor");
因为它的super()
引用了父类构造函数,它是
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");
结果你会看到
父初始值设定项块
父构造函数
这将处理使用super()
执行的Parent#constructor()
,因此接下来您将看到子构造函数在super()
之后生成的代码