首页 > 解决方案 > 为什么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

标签: javastatic

解决方案


当一个类被加载和链接时,它的static字段都被初始化为它们的默认值。完成后,静态字段初始化程序将按照它们在文件中出现的顺序执行,从而完成类的初始化。所有这些都发生在该类中定义的任何代码执行之前。所以这里发生的是:

  1. RED, GREEN, BLUE, 和i被初始化为它们的默认值(null字段Color和 0 i)。请注意,这与任何初始化程序无关。
  2. RED字段( )的初始化程序RED = new Color()执行。作为副作用,i递增到 1。
  3. 字段的初始化程序BLUE执行并i递增到 2。
  4. field 的初始化程序GREEN执行并i递增到 3。
  5. static字段的初始化程序i执行并被i赋值为 0。
  6. 该方法在开始执行时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


推荐阅读