面临构造函数静态块和代码块执行顺序的问题

Par*_*tho 3 java polymorphism inheritance static constructor

我知道当我创建一个实例静态块时首先初始化然后代码块然后构造函数在这里我的代码

public class Main{

public Main() {
    out.println("constructor initialised");
}

static {
    out.println("static block initialised");
}
{
    out.println("Code block initialised");
}

public static void main(String... args) {

    new Main();
}

}
Run Code Online (Sandbox Code Playgroud)

像这样输出

静态块初始化
代码块初始化
构造函数初始化

上面的输出清除了我的概念,但是当我扩展这样的类时

public class Main extends Bear{

public Main() {
    out.println("constructor initialised");
}

static {
    out.println("static block initialised");
}
{
    out.println("Code block initialised");
}

public static void main(String... args) {
    new Main();
}
}
Run Code Online (Sandbox Code Playgroud)

熊类

class Bear{
static {
    out.println("static block initialised of bear class");
}

{
    System.out.println("Code bLock initialised of bear class");
}

void run() {
    out.println("running...");
}
}
Run Code Online (Sandbox Code Playgroud)

输出如下:

静态块初始化熊类
静态块初始化
代码块初始化熊类
代码块初始化
构造函数初始化

当扩展类时,执行顺序改变了我不明白为什么会发生上面的输出

Wil*_*fat 5

我相信这些工作的方式是:

  • 静态块在第一次加载类时被调用(基本上是你第一次在项目中使用类),所以这些首先发生
  • 初始化(代码)块基本上在开始时(在调用 super() 之后)复制到每个构造函数中,因此您可以共享代码(虽然不是很好的风格)
  • 构造函数很好……构造函数……

它们按此顺序出现的原因是因为子类依赖于现有的父类。子类不能在父类之前加载,所以调用父类的静态初始化器来加载它,然后再加载子类。

加载每个类后,它将调用构造函数(包括非静态代码块)来初始化您的对象。同样,子类依赖于父类存在并正确设置,因此首先调用基类构造函数,然后调用派生类构造函数。需要按此顺序完成,以便子类可以依赖父类的某些参数。如果您在基类中添加了显式构造函数,您将获得如下输出:

类已加载

  • 熊类的静态块初始化
  • 静态块初始化

基类构造函数

  • 熊类的代码块初始化
  • 构造函数初始化熊类

子类构造函数

  • 代码块初始化
  • 构造函数初始化

如果您两次调用 new Main() ,您会第一次看到上面的输出,但第二次可能会丢失静态块,因为该类已经被加载。

  • 值得注意的是,初始化块在调用 SUPER 之后被复制到构造函数中。这很重要,因为这就是为什么 Bear 的初始化程序块首先发生(Main 隐式调用 super 到 Bear。Bear 隐式调用 super 到 Ovject,然后运行初始化程序,然后我们回到 Main(在隐式 super 调用之后),然后运行它初始化块,然后返回到 Main 构造函数的其余部分)。 (3认同)