public class StaticTest {
private static StaticTest stObj=new StaticTest();
private static int VAR1=10;
private static final int VAR2=20;
public StaticTest() {
System.out.println("Var1 : "+VAR1);
System.out.println("Var2 : "+VAR2);
}
public static void main(String[] args) {
System.out.println("VAR1 after constrution : "+StaticTest.VAR1);
}
}
输出:
Var1:0 Var2:20 构造后的VAR1:10
为什么VAR1和VAR2会有这种不同的行为?
答案 0 :(得分:5)
静态字段按声明顺序逐个初始化。
在您的特定情况下,首先初始化StaticTest stObj
。这在VAR1
初始化之前执行。因此,VAR1
在打印时会带有默认值。
但是VAR2
是编译时常量,因此编译器会优化其初始化并首先进行初始化。这样,其中一个变量在您调用构造函数时初始化,另一个 - 不是。
答案 1 :(得分:3)
VAR2
是一个编译时常量,因此它的值被“烘焙”到每个调用站点。因此,在期望看到它初始化之前,使用它并不重要。如果在编译器方面将其更改为不是的常量,例如。
private static final int VAR2 = "xyz".length();
然后你会看到与VAR1
相同的行为(就输出而言)。
有关常量表达式的详细信息,请参阅section 15.28 of the JLS。
答案 2 :(得分:0)
VAR1
可以更改,VAR2
不能。
试试这个:
private static int VAR1=10;
private static final int VAR2=20;
public static void main(String[] args) {
VAR1 = 25;
VAR2 = 35; // You'll find a compilation error here.
}
答案 3 :(得分:0)
VAR2
无法更改,而该类的任何实例可以在以后更改VAR
。
这里的问题是你在变量完全初始化之前引用该变量。
private static StaticTest stObj=new StaticTest();
private static int VAR1=10;
private static final int VAR2=20;
在初始化其他静态成员之前,您正在加载类本身时创建该类的实例。
检查Java Language Specifications for more details (Chapter 12)。
(通常,在自己构建过程中创建类的实例会导致问题:你应该避免这种情况。)