Java 最终字段初始化顺序

Java 最终字段初始化顺序,java,jls,Java,Jls,下面是一些对尚未初始化的类调用静态方法A.f()的代码。 有人可以用JLS来解释此代码的行为吗 class A { final static Object b = new B(); final static int S1 = 1; final static Integer S2 = 2; static void f() { System.out.println(S1); System.out.println(S2); }

下面是一些对尚未初始化的类调用静态方法A.f()的代码。 有人可以用JLS来解释此代码的行为吗

class A {
    final static Object b = new B();
    final static int S1 = 1;
    final static Integer S2 = 2;

    static void f() {
        System.out.println(S1);
        System.out.println(S2);
    }
}

class B {
    static {
        A.f();
    }
}

public class App
{
    public static void main( String[] args )
    {
        A.f();
    }
}
输出:

1
null
1
2
App.main()
中的
A.f()
触发类
A
的初始化

所有常量变量都已初始化。唯一的常量变量是
S1
,现在是
1

然后,按照文本顺序初始化其他静态字段
b
是第一个字段,它触发类
b
的初始化,然后调用
A.f()
S2
只是
null
,因为它尚未初始化。
b
的初始化现已完成。最后但并非最不重要的一点是,
S2
被初始化为
Integer
对象
2

S2
不是常量变量,因为它不是基元类型
int
,而是引用类型
Integer
<代码>S2=2是
S2=Integer.valueOf(2)的自动装箱缩写

如果字段声明中的声明符具有变量初始值设定项,则声明符具有声明变量赋值(§15.26)的语义

[……]

注意,作为常量变量(§4.12.4)的
static
字段在其他
static
字段(§12.4.2)之前初始化。这也适用于接口(§9.3.1)。即使通过迂回的程序,也不会观察到此类字段具有默认初始值(§4.12.5)

常量变量是原始类型或类型
String
final
变量,用常量表达式初始化(§15.28)。变量是否为常量变量可能涉及到类初始化(§12.4.1)、二进制兼容性(§13.1、§13.4.9)和确定赋值(§16(确定赋值))

常量表达式是表示原语类型的值或
字符串的表达式,它不会突然完成,并且仅使用以下内容组成:

  • 原语类型的文字和
    字符串类型的文字
[……]

对于每个类或接口C,都有一个唯一的初始化锁
LC
。从C到
LC
的映射由Java虚拟机实现自行决定。初始化C的步骤如下:

[……]

  • 否则,记录当前线程正在初始化C的
    对象,然后释放
    LC

    然后,初始化C的
    静态
    字段,这些字段是常量变量(§4.12.4、§8.3.2、§9.3.1)

  • [……]

  • 接下来,按照文本顺序执行类的类变量初始值设定项和静态初始值设定项,或者执行接口的字段初始值设定项,就像它们是单个块一样
  • 程序中的每个变量在使用其值之前必须有一个值:

    • 每个类变量、实例变量或数组组件在创建时都会使用默认值进行初始化(§15.9、§15.10.2):

      [……]

      • 对于所有参考类型(§4.3),默认值为
        null

    这个问题似乎不属于
    JLS
    ,但我们已经处理了
    JVM

    解析
    过程之前的
    链接
    阶段,有一个子阶段,包括:

    为类或接口创建静态字段并初始化 将这些字段设置为其默认值

    还有更多:

    静态字段的显式初始值设定项作为 初始化(§5.5),而非准备

    而其中包括:

    任何一条Java虚拟机指令的执行都是新的


    初始化基元类型包括写入它们的初始值。对于引用类型字段,其默认值为
    null
    ,因为在子阶段之前,jvm不“知道”哪个类与类的适当符号引用名称关联

    我想每个人都同意,令人印象深刻的部分是
    null
    一个,原始对象初始化与非原始对象初始化有一定的优先级,但这与第9步中提到的“文本顺序”有什么关系?@SpaceTrucker是你的问题,为什么
    S1
    b
    之前被初始化<代码>S1
    在上述章节的步骤6中初始化。