当我们第一次使用类时,静态代码是否总是执行的?

2022-09-04 07:09:01

我们的应用程序使用的初始化代码取决于静态代码的执行顺序,我想知道这个顺序是否在所有JVM中都是一致的。

以下是我的意思示例:


public class Main {

    static String staticVar = "init_value";

    public static void main(String[] args) {

        System.out.println(A.staticVar);
        staticVar = "mainValue";
        System.out.println(A.staticVar);
    }
}

public class A {
    static String staticVar = Main.staticVar;
}

将给予:

init_value
init_value


public class Main {

    static String staticVar = "init_value";

    public static void main(String[] args) {

        // System.out.println(A.staticVar);
        staticVar = "mainValue";
        System.out.println(A.staticVar);
    }
}

public class A {
    static String staticVar = Main.staticVar;
}

将给予(在我的环境中):

mainValue

总而言之,在所有 JVM 中,当我们第一次使用类时,静态代码是否总是执行的?


答案 1

编辑:尽管下面有保证,但如果你想依靠这种东西,我会努力重构你的代码,这样它就不会突然出现。虽然它保证可以正常工作,但它也可能使您的代码非常脆弱。静态初始值设定项被称为“无形”的事实使它们相对难以推理和调试。


是的,这是由语言规范保证的。从规范的第 8.7 节中

类中声明的任何静态初始值设定项在类初始化时执行,并且与类变量的任何字段初始值设定项 (§8.3.2) 一起可用于初始化类的类变量 (§12.4)。

静态初始化程序:阻止static

静态初始值设定项能够突然完成 (§14.1, §15.6), 但有一个选中的异常 (§11.2),这是一个编译时错误。如果静态初始值设定项无法正常完成,则为编译时错误 (§14.21)。

静态初始值设定项和类变量初始值设定项按文本顺序执行。

第12.4节开始:

类的初始化包括执行其静态初始值设定项和类中声明的静态字段的初始值设定项。接口的初始化包括为接口中声明的字段执行初始值设定项。

在初始化类之前,必须初始化其直接超类,但不需要初始化该类实现的接口。同样,接口的超接口在初始化接口之前不需要初始化。

类或接口类型 T 将在首次出现以下任一项之前立即初始化:

  • T 是一个类,并创建了 T 的一个实例。
  • T 是一个类,调用由 T 声明的静态方法。
  • 分配由 T 声明的静态字段。
  • 使用 T 声明的静态字段,并且该字段不是常量变量 (§4.12.4)。
  • T 是顶级类,并且是词法嵌套的断言语句 (§14.10)

答案 2

静态初始化器(例如,您的 staticVar 声明)总是在您第一次使用类时执行。

静态方法仅在调用时执行。在你的例子中,发生这种情况是因为静态 void main(String[] args) 是应用程序的入口点。但是,如果您定义了不同的静态方法,则不会调用它。

还可以创建一个静态初始化器块,该块也将在首次使用类之前自动调用,例如

static {
  // some initialisation code here
}

推荐