我有一个名为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);
}
}
Run Code Online (Sandbox Code Playgroud)
出局如下:
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
Run Code Online (Sandbox Code Playgroud)
加载并链接类时,其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()方法i在main()开始执行时执行并产生与0 一致的结果.你可以在阅读这一切的血淋淋的细节Java语言规范(JLS)第12章和Java虚拟机规范的第5章.
只需将声明移到字段i前面即可获得预期的输出Color:
static int i=0;
public static Color RED = new Color();
public static final Color BLUE = new Color();
public static final Color GREEN = new Color();
Run Code Online (Sandbox Code Playgroud)
然后输出将是:
增加'i'在这里1
增加'i'在这里2
增加'i'在这里
3'i'变量在这里没有增加,它仍然显示'0','i'是:3
增加'i'这里4
4
需要注意的是final修饰符这里是因为初始化的顺序没有任何影响GREEN和BLUE是不是"常变量"根据在JLS该术语的定义.甲常量变量(字的一个不幸的配对)是一个原始或String既声明的变量final并初始化为一常量表达式.在这种情况下,new Color()不是常量表达式,Color并且不是常量变量的合适类型.例如,参见JLS的§4.12.4.