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

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

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();
}

}

像这样输出

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

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

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();
}
}

熊类

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...");
}
}

输出如下:

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

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

回答

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

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

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

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

类已加载

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

基类构造函数

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

子类构造函数

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

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

  • Worth noting that initialiser blocks are copied into the constructor AFTER THE CALL TO SUPER. This is important as it is why Bear’s initialiser block happens first (Main implicitly calls super to Bear. Bear implicitly calls super to Ovject, and then runs initialiser, then we’re back in Main (after the implicit super call) and so run it’s initialiser block, and then back to the rest of Main’s constructor).

以上是面临构造函数静态块和代码块执行顺序的问题的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>