我正在研究Java中的静态初始化器。我通过以下给出了源代码:
public class A {
private static int count = 5;
final static int STEP = 10;
boolean alive;
static {
count = 1;
}
public static void main(String[] args) {
A a = new A();
System.out.println(A.count);
}
}
我的问题是,编译器为什么不抱怨变量count
被重新分配给静态初始化程序块中1
中的值count = 1
。我知道Java允许前向引用,只要遵循声明前读取规则(即,在声明之前不应读取任何标识符),这适用于所有初始化程序,如果不是,那么引用(或标识符) )必须在作业的左侧。我也知道如果在类中写入多个静态初始化表达式和静态字段初始化程序块,那么它们的执行顺序是顺序的。
根据我的说法,执行流程应该是:加载类,然后按顺序执行所有静态初始化程序(表达式和块),因此count
将被初始化为值{{1然后执行默认构造函数,调用super()并将实例变量5
初始化为默认值。但是为什么不抛出静态变量alive
已被重新初始化的错误(因为它不是前向引用的情况),而是给出输出count
。
这是否意味着我们可以通过静态初始化程序块重新初始化静态变量?
答案 0 :(得分:2)
由于你的类变量在使用前出现,没关系。
以下是同一
的language specification#Static Initializers
在类初始化时执行类中声明的静态初始化程序(第12.4.2节)。与类变量的任何字段初始值设定项(第8.3.2节)一起,静态初始值设定项可用于初始化类的类变量。
使用类变量,其声明在使用后以文本形式出现有时会受到限制,即使这些类变量在范围内也是如此。有关控制类变量的正向引用的精确规则,请参见§8.3.3。
答案 1 :(得分:1)
只要您在类中操作静态变量,它就会被初始化,您将不会从编译器中获得错误。如果您已将其声明为最终,那么您提到的行为就会发生。请记住,静态意味着变量在对象的所有实例之间共享,因此它只被初始化并分配一次内存。