为什么java静态变量没有更新?
我有一个名为Color的类,其中有三个静态对象(用同一个类本身实例化)和一个int类型(称为I)变量。当我运行这个类时,“I”变量在构造函数中是递增的,但它没有在内存中持久化,请在下面解释这个代码
package test;
public class Color
{
public static Color RED = new Color();
public static final Color BLUE = new Color();
public static final Color GREEN = new Color();
static int i=0;
Color(){
System.out.println("Incrementing 'i' here "+(++i));
}
public static void main(String[] args) {
System.out.println("The 'i' variable is not incremented here, it still shows '0' , 'i' is: "+ Color.i ); // line 14
Color x = new Color();
System.out.println(x.i);
}
}
结果如下:
Incrementing 'i' here 1
Incrementing 'i' here 2
Incrementing 'i' here 3
The 'i' variable is not incremented here, it still shows '0' , 'i' is: 0
Incrementing 'i' here 1
1
# 1 楼答案
加载并链接一个类时,它的
static
字段都初始化为默认值。完成后,静态字段初始值设定项将按照它们在文件中出现的顺序执行,从而完成类的初始化。所有这些都发生在该类中定义的任何代码执行之前。所以这里发生的事情是:RED
、GREEN
、BLUE
和i
被初始化为它们的默认值(null
用于Color
字段,0用于i
)。请注意,这与任何初始值设定项无关李>RED
(RED = new Color()
)的初始值设定项。作为副作用,i
增加到1李>BLUE
的初始值设定项,并且i
增加到2李>GREEN
的初始值设定项,并且i
增加到3李>static
字段i
的初始值设定项,并且i
被赋值为0李>main()
方法,并在main()
开始执行时生成与i
为0一致的结果李>你可以在Chapter 12 of the Java Language Specification (JLS)和Chapter 5 of the Java Virtual Machine Specification中阅读这一切的血腥细节
只需将
i
的声明移到Color
字段之前,即可获得预期的输出:然后输出将是:
注意
final
修饰符对这里的初始化顺序没有影响,因为GREEN
和BLUE
根据JLS中该术语的定义不是“常量变量”。常量变量(一个不幸的词对)是一个原语或String
变量,它既是声明的final
又初始化为常量表达式。在这种情况下,new Color()
不是常量表达式,Color
不是常量变量的合适类型。例如,见§4.12.4 of the JLS# 2 楼答案
类初始化从上到下进行。当我们初始化颜色时,我们会创建一种新的颜色。为了创建新颜色,我们还必须初始化颜色。这叫做递归初始化,系统所做的只是忽略递归初始化并执行
new Color()
。该类初始值设定项按以下顺序自上而下执行public static Color RED = new Color();
这将静态变量i设置为1public static final Color BLUE = new Color();
这将静态变量i增加到2public static final Color GREEN = new Color();
这将静态变量i增加到3static int i=0;
这将静态变量i设置回零现在当主线程运行时。它将静态变量设置为0,并递增为1
作为反例,尝试将
static int i=0
替换为static Integer i=new Integer(0).
。这将抛出一个NullPointerException
。这是因为在类初始化时,当public static Color RED = new Color();
执行时,它会将i视为null,因为那时我还没有初始化,导致NullPointerException