下面是一些在尚未初始化的类上调用静态方法Af()的代码.有人可以用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();
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
1
null
1
2
Run Code Online (Sandbox Code Playgroud)
xeh*_*puk 29
A.f()在App.main()触发器初始化类A.
初始化所有常量变量.唯一的常量变量是S1,现在是1.
然后,以文本顺序初始化其他静态字段.b是第一个字段,它触发类的初始化,B然后调用A.f().S2只是null因为它尚未初始化.初始化b现已完成.最后但并非最不重要的S2是,初始化为Integer对象2.
S2不是常量变量,因为它不是基本类型int而是引用类型Integer.S2 = 2;是一种自动拳击速记S2 = Integer.valueOf(2);.
如果字段声明中的声明符具有变量初始值设定项,则声明符具有声明变量的赋值(第15.26节)的语义.
[...]
请注意,
static作为常量变量的static字段(第4.12.4节)在其他字段(第12.4.2节)之前初始化.这也适用于接口(第9.3.1节).即使是狡猾的程序,也永远不会观察到这些字段具有默认的初始值(§4.12.5).
甲常量变量是
final原始类型或类型的变量String,其与一个常量表达式(§15.28)初始化.变量是否是常量变量可能对类初始化(第12.4.1节),二进制兼容性(第13.1节,第13.4.9节)和明确赋值(第16节(定义赋值))有影响.
甲常量表达式是表示原语类型的值的表达式或
String不突然完成并且使用仅由以下内容:
- 原始类型的文字和类型的文字
String[...]
对于每个类或接口C,都有一个唯一的初始化锁
LC.从C到C的映射由LCJava虚拟机实现决定.初始化C的过程如下:[...]
否则,记录
Class当前线程正在进行C对象初始化并释放的事实LC.然后,初始化
staticC 的字段,它们是常量变量(§4.12.4,§8.3.2,§9.3.1).[...]
- 接下来,按文本顺序执行类的类变量初始值设定项和类的静态初始值设定项,或接口的字段初始值设定项,就好像它们是单个块一样.
程序中的每个变量在使用其值之前必须具有值:
每个类变量,实例变量或数组组件在创建时都会使用默认值进行初始化(§15.9,§15.10.2):
[...]
- 对于所有引用类型(§4.3),默认值为
null.