java - 为什么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
解决方案
当一个类被加载和链接时,它的static
字段都被初始化为它们的默认值。完成后,静态字段初始化程序将按照它们在文件中出现的顺序执行,从而完成类的初始化。所有这些都发生在该类中定义的任何代码执行之前。所以这里发生的是:
RED
,GREEN
,BLUE
, 和i
被初始化为它们的默认值(null
字段Color
和 0i
)。请注意,这与任何初始化程序无关。RED
字段( )的初始化程序RED = new Color()
执行。作为副作用,i
递增到 1。- 字段的初始化程序
BLUE
执行并i
递增到 2。 - field 的初始化程序
GREEN
执行并i
递增到 3。 - 该
static
字段的初始化程序i
执行并被i
赋值为 0。 - 该方法在开始执行时
main()
执行并产生与i
为0一致的结果。main()
您可以在 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();
然后输出将是:
此处递增 'i' 1 此处
递增 'i' 2 此处
递增 'i' 3 此处
'i' 变量不递增,仍显示 '0' ,'i' 为: 3
此处递增 'i' 4
4
请注意,final
修饰符对此处的初始化顺序没有影响,因为根据 JLS 中该术语的定义,GREEN
并且BLUE
不是“常量变量”。常量变量(不幸的单词对)是一个原语或变量String
,既声明final
又初始化为常量表达式。在这种情况下,new Color()
不是常量表达式,Color
也不是常量变量的合适类型。例如,参见JLS 的 §4.12.4。
推荐阅读
- javascript - 未捕获的 SyntaxError:意外的令牌“var”错误
- javascript - 如何同时使用 router.get 和 https.get?(Node.js)
- javascript - 有没有办法改变 RSuite-table 中空数据的消息?
- python-3.x - Python unittest类问题
- rust - 如何在 Rust 中创建不同 Future 特征之间的互操作性?
- c++ - 使用 QT 取消引用 std::unique_ptr 时出现问题(分段错误)
- python-3.x - 如何避免将大尺寸的固定值数组传递给函数?
- javascript - 从 lat/lng 确定 SegmentId
- python - python函数是可变对象吗?函数的局部变量是它的属性吗?
- javascript - JS/CSS 加载微调器在 JS 执行之前完成