我们的应用程序正在使用依赖于执行静态代码的顺序的初始化代码,我想知道这个顺序是否在所有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中,当我们第一次使用类时,是否总是执行静态代码?
答案 0 :(得分:18)
编辑:尽管下面有所有的保证,如果你正在考虑依赖这类事情,我会尽力重构你的代码,以免它出现。虽然 保证可以正常工作,但它也可能使您的代码非常脆弱。静态初始化程序被称为“不可见”的事实使得它们相对难以推理和调试。
是的,这是由语言规范保证的。来自规范的section 8.7:
在类初始化时执行在类中声明的任何静态初始值设定项,并且与类变量的任何字段初始值设定项(第8.3.2节)一起,可用于初始化类的类变量(第12.4节)。
StaticInitializer:
static
阻止静态初始化程序能够通过检查异常(第11.2节)突然完成(第14.1节,第15.6节)是编译时错误。如果静态初始化程序无法正常完成,则为编译时错误(§14.21)。
静态初始值设定项和类变量初始值设定项以文本顺序执行。
来自section 12.4:
一个类的初始化包括 执行静态初始化程序和 静态字段的初始值设定项 在课堂上宣布。初始化 接口包括执行 声明的字段的初始值设定项 在界面中。
上课之前 初始化,它的直接超类 必须初始化,但接口 由班级实施不必 初始化。同样, 接口需要的超接口 不要在之前初始化 接口已初始化。
类或接口类型T将是 在此之前立即初始化 第一次出现任何一个 以下内容:
- T是一个类,T的实例是 创建。
- T是一个类和一个静态 调用T声明的方法。
- 甲 T声明的静态字段是 分配
- T声明的静态字段 使用,字段不是 常数变量(§4.12.4)。
- T是一个 顶级类和断言 声明(§14.10)词汇嵌套
答案 1 :(得分:4)
第一次使用类时,始终会执行静态初始化程序(例如,staticVar声明)。
静态方法仅在调用时执行。在您的情况下,这发生了,因为静态void main(String [] args)是应用程序的入口点。但是如果你定义了一个不同的静态方法,那么就不会调用它。
也可以创建一个静态初始化块,在初次使用类之前也会自动调用它,例如
static {
// some initialisation code here
}
答案 2 :(得分:3)
在所有平台上应该都是一样的。请参阅JVM规范:http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc.html#19075
答案 3 :(得分:2)
Java规范的引用:
类的初始化包含 执行静态初始化程序和 静态字段的初始值设定项 在课堂上宣布。初始化 接口包括执行 声明的字段的初始值设定项 在界面中。
答案 4 :(得分:1)
是的,根据Java Language Specification静态代码总是在所有(兼容的)JVM上以相同的顺序执行。
静态初始值设定项和类变量初始值设定项以文本顺序执行。
答案 5 :(得分:1)
Dittos对其他海报,但让我补充说,依赖于你的例子中其他类的状态的静态初始化程序在我看来是非常脆弱和难以维护的代码。我将使用静态初始化器来填充内部类数据 - 用默认值或类似的东西填充数组。但我不认为我曾经看过另一堂课的数据。技术上合法,也许有一些奇怪的情况,这是一个好主意,但是很糟糕。
答案 6 :(得分:0)
是的,我相信根据定义,这将是重点。
答案 7 :(得分:0)
静态块将始终首先运行,而不仅仅是第一次 ...在执行任何代码块JVM execute the static code block first
之前,然后只运行代码块,因为它已经设计好了。 ..