静态块vs初始化块与继承中的构造函数

ous*_*dri 1 java polymorphism inheritance constructor static-block

我找到这个例子,我想了解它背后的逻辑?构造函数和静态块以及初始化程序块如何在继承中工作?在哪个阶段被称为?

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

i am Parent 3
i am son 3
i am parent 2
i am parent 1
i am son 2
i am son 1
Run Code Online (Sandbox Code Playgroud)

Psh*_*emo 11

你需要知道这一点

  1. 构造函数中的第一条指令是调用其父类的构造函数,super(params)或者是否要使用默认构造函数super().在默认构造函数的情况下,您不必显式编写它.
  2. 初始化程序块中的代码在super(...)调用后立即移动到每个构造函数
  3. 初始化类时执行静态块,这是在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();
    }
}
Run Code Online (Sandbox Code Playgroud)

为了能够mainSon类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");
Run Code Online (Sandbox Code Playgroud)

由于它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");
Run Code Online (Sandbox Code Playgroud)

结果你会看到

  • 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();
Run Code Online (Sandbox Code Playgroud)

这将导致

Parent static block
Son static block
ABC                      // before new Son()
Parent initializer block
Parent constructor
Son initializer block
Son constructor
Run Code Online (Sandbox Code Playgroud)


JB *_*zet 9

当类由JVM加载并初始化时,会调用一次静态块.在构造类的实例时执行实例初始化程序,就像构造函数一样.

静态和实例初始值设定项在Java语言规范中描述

  • 而且,显然,它在构造函数之前被调用。 (2认同)