v2
为空,但如果我提出v2
的声明&在instance
之前初始化它将有一个值;这是为什么?
public class A {
private static final String v1 = new String(new byte[]{'a', 'b'});
private static A instance = new A();
private static final String v2 = new String(new byte[]{'b', 'c'});
private A() {
System.out.printf("A c'tor\tv1 [%s]\tv2 [%s]\n", v1, v2);
}
public static void main(String[] args) {
System.out.println("start main");
new A();
System.out.println("end main");
}
}
输出:
A c'tor v1 [ab] v2 [null]
start main
A c'tor v1 [ab] v2 [bc]
end main
另外,如果我将v2
的初始化更改为:
private static final String v2 = "ab";
它会初始化v2
,输出为:
A c'tor v1 [ab] v2 [ab]
start main
A c'tor v1 [ab] v2 [ab]
end main
修改
第二部分的另一个测试:
public class A {
private static final String v1 = new String(new byte[]{'a', 'b'});
private static transient A instance = new A();
private static final String v2 = new String(new byte[]{'b', 'c'});
private static final String v3 = new String("ab");
private static final String v4 = "ab";
private A() {
System.out.printf("A c'tor\tv1 [%s] v2 [%s] v3 [%s] v4 [%s]\n", v1, v2, v3, v4);
}
public static void main(String[] args) {
System.out.println("start main");
new A();
System.out.println("end main");
}
}
输出:
A c'tor v1 [ab] v2 [null] v3 [null] v4 [ab]
start main
A c'tor v1 [ab] v2 [bc] v3 [ab] v4 [ab]
end main
答案 0 :(得分:3)
静态变量按照初始化类A时(在执行main
之前)在源文件中出现的顺序进行初始化。
A c'tor v1 [ab] v2 [null]
,因为它的初始化涉及创建A的实例) - 它在v2
之前初始化,这就是v2
仍为null
的原因。 初始化后,执行main
方法,并生成接下来的3个输出行。在A
方法中创建main
的新实例会产生与前一个构造函数调用不同的输出,因为此时v1
和v2
都被初始化。 / p>
编辑:
关于您更新的问题:
如果您关注initialization procedure in JLS 12.4.2:
- 否则,记录当前线程正在进行C的Class对象初始化并释放LC的事实。然后,初始化接口的最终类变量和字段,其值为编译时常量表达式。
醇>...
- 接下来,执行类的类变量初始值设定项和静态初始值设定项,或接口的字段初始值设定项,按文本顺序,就像它们是单个块一样。
醇>
如您所见,其值为compile-time constant expressions的最终静态变量在其余静态变量之前初始化。因此,将v2
的值更改为常量"ab"
会导致v2
在instance
变量之前初始化,这解释了不同的输出。