【问题标题】:Order of static initialization blocks静态初始化块的顺序
【发布时间】:2014-12-24 05:18:36
【问题描述】:

我发现了很多关于静态初始化块的帖子,但是我试图更好地了解执行顺序及其原因。下面的代码打印出两个静态块中的文本,“然后”打印出主静态块中的文本。

我理解编译器调用它的方式是在加载类时按顺序执行所有静态块,然后访问 main 方法。但是由于主要方法本身是静态的,为什么不按其他静态块的顺序执行它(甚至不确定它是否有用,只是试图理解一个概念,以及是否有紧迫的理由这样做)。如果我们想在主块之后运行静态块怎么办?

class Cat {

    static
    {
        System.out.println("This block welcomes you first");
    }

    public static void main(String[] args)
    {
        System.out.println("Meow world ");
    }

    static
    {
        System.out.println("This block welcomes you after");
    }
}

实际输出

This block welcomes you first
This block welcomes you after
Meow world 

为什么不呢?

This block welcomes you first
Meow world 
This block welcomes you after

【问题讨论】:

  • 因为静态块的代码在加载类之后调用它的main方法之前立即执行
  • 不要混淆static 方法static 初始化块
  • 我认为这回答了我的问题。 main 仍然是一个静态的“方法”,而其余的是初始化块。它们在类加载时运行而不被调用。所以这些块出现在哪里并不重要(在 main 之前或之后——它们总是在类加载后首先运行)
  • @aparna - 对。但请记住,静态初始化程序是按顺序执行的,即它们的出现方式和方式。
  • "如果我们想在主块之后运行一个静态块怎么办?"那将是一个终结器块,而不是一个初始化器块。您可以添加一个关闭挂钩(请参阅stackoverflow.com/questions/5747803/…),或在 main 方法中添加一个 try...finally 语句。

标签: java static


【解决方案1】:

加载类后立即执行静态初始化程序。 main 方法在类被加载后调用

JLS 的这一部分讨论了事件的顺序 (12.1.3-4):

12.1.3。初始化测试:执行初始化程序

在我们接下来的示例中,Java 虚拟机仍在尝试执行 Test 类的 main 方法。仅当类已初始化时才允许这样做(第 12.4.1 节)。

初始化包括按文本顺序执行 Test 类的任何类变量初始化程序和静态初始化程序。 但在初始化 Test 之前,必须初始化其直接超类以及直接其直接超类的超类,以此类推,递归。在最简单的情况下,Test 将 Object 作为其隐式直接超类;如果类 Object 尚未初始化,则必须在初始化 Test 之前对其进行初始化。类 Object 没有超类,所以递归在这里终止。


12.1.4。调用 Test.main

最后,Test类初始化完成后(在此期间可能发生了其他后续加载、链接和初始化),调用Test的main方法。

【讨论】:

  • 一旦类被初始化 :)
【解决方案2】:

运行时系统保证静态初始化块按照它们在源代码中出现的顺序被调用。别忘了,这段代码会在 JVM 加载类时执行。 JVM 将所有这些块组合成一个静态块,然后执行。这里有几点我想提一下:

If you have executable statements in the static block, JVM will automatically execute these statements when the class is loaded into JVM.
If you’re referring some static variables/methods from the static blocks, these statements will be executed after the class is loaded into JVM same as above i.e., now the static variables/methods referred and the static block both will be executed.

之后将执行 main 方法。 谢谢

【讨论】:

    【解决方案3】:

    静态初始化器在类被初始化后立即执行(类可以在稍后的时间点被加载和初始化。检查Class.forName())。 main() 方法在静态初始化程序执行后调用。所以输出是这样的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-12
      • 2010-09-17
      • 1970-01-01
      • 1970-01-01
      • 2019-05-21
      相关资源
      最近更新 更多