谁能解释为什么这两种代码都按此顺序打印输出的原因(静态关键字执行优先级)

Could anyone explain the reason why output is printed in this order for both the codes(Static keyword execution priority)

代码 1:

    public class test {
        static {System.out.println("I am here in static");}
        public test()
        {
            System.out.println("I am here in constructor");
        }
    
        public static void main(String[] args)
        {
            System.out.println("I am here in Main");
            test staticCheck=new test();
        }

输出 1: 我在这里静态 我在这里主要 我在构造函数中

代码 2:

    public class test {
        {System.out.println("I am here in static");}
        public test()
        {
            System.out.println("I am here in constructor");
        }
    
        public static void main(String[] args)
        {
            System.out.println("I am here in Main");
            test staticCheck=new test();
    
        }
    
    }

输出 2: 我在这里主要 我在这里静态 我在构造函数中

因为写CODE 2的人都是骗子

CODE 2 中的“I am here in static”应该改为“I am here in instance initialization block”。 IIBs 运行 每次在构造函数之前初始化实例。

更多内容见this tutorial

在代码 1 中,行 static {System.out.println("I am here in static");} 是一个 静态初始化 块(也称为 静态初始化程序)。静态初始化程序块是用大括号 { } 括起来的普通代码块,前面有 static 关键字。这些块用于解决特定 class 在调用构造函数之前 可能具有的依赖项。将它们视为先决条件。因为 static 成员属于 class 而不是对象(实例),所以必须在创建任何实例之前加载它们(发生一次)。

在代码 2 上,当关键字 static 被移除时,该块变为 Initializer 块。初始化程序块类似于静态初始化程序,除了它们必须发生在创建 class 实例的过程中。因此,它们将在每个创建的实例中执行一次。因此,如果您要向 main 方法添加另一行以创建 test 的第二个实例,您的输出将是:

I am here in Main
I am here in static
I am here in constructor
I am here in static
I am here in constructor

请注意“我在静态中”和“我在构造函数中”出现了两次(每个实例一次)并且初始化程序块在构造函数之前执行。这些初始化程序块的使用不是很普遍,但在您有一系列可以由 class 的所有构造函数共享的指令的情况下,它们很有用。你可以看到为什么很少使用它。

如果我们重新添加 static 关键字,创建了两个对象的程序的输出将是:

I am here in static
I am here in Main
I am here in constructor
I am here in constructor

正如我之前提到的,因为初始化器现在是 static 它只出现一次。

“I am here in Main”和“I am here in constructor”的执行顺序不需要解释。但是,以防万一,因为这是它们在 main 方法中出现的顺序:System.out.println("I am here in Main") 发生在 staticCheck 对象被实例化之前。

UPDATE:这有点超出范围,但相关。如果要将父级 class 添加到此处显示的 class,则执行顺序如下:

  1. 打印父class静态初始化器
  2. 的内容
  3. 打印出这个class(子)静态初始化器的内容
  4. 打印出“我在 Main 这里”
  5. 打印父class(如果有的话)的非静态初始值设定项
  6. 打印父构造函数的内容
  7. 打印出这个(子)的非静态初始值设定项class
  8. 打印出这个class构造函数的内容