枚举的构造函数和静态初始化程序

5

我在处理枚举时感到有些困难。以下是Kathy Siera书中的一个示例:

    public class WeatherTest {

    static Weather w;

    public static void main(String[] args) {
        System.out.print(w.RAINY.count + " " + w.Sunny.count + " ");
    }
}

enum Weather {

    RAINY, Sunny;
    int count = 0;

    Weather() {
        System.out.print("c ");
        count++;
    }
}

输出结果是 c c 1 1。明白了。 现在我想,如果计数字段是静态的会怎样呢?输出会变成 c c 2 2 吗? 基于这个想法,我把计数变量改成了静态的。 但是我看到的是这样的: 编译时错误:从初始化程序引用静态字段非法。 在网上搜索后,我发现这是Sun公司的一种漏洞,它允许可以更改静态字段的静态方法。好的,现在我使用一个静态方法incr来完成我的工作:
     class WeatherTest {

    static Weather w;

    public static void main(String[] args) {
        System.out.print(w.RAINY.count + " " + w.Sunny.count + " ");
    }
}

enum Weather {

    RAINY, Sunny;

    Weather() {
        System.out.print("c ");
        incr();
    }
    static int count = 0;

    static void incr() {
        count++;
    }
}

出乎意料的是,我得到了这样的输出:c c 0 0!有谁可以在我开枪前解释一下这种行为吗?

请修正您的缩进和大括号。 - ardent
非常棘手的问题!所有Java程序员,武装起来 :) - Kameron
在进行任何操作之前,请访问 http://www.suicidepreventionlifeline.org/。 - Alexander Pogrebnyak
1个回答

6

枚举值可以被认为是被高度赞扬的静态字段(它们在底层实现时就是这样的)。

因此,如果你的 Weather 是一个普通的Java类,那它会像这样:

 class Weather {
   public final static Weather RAINY = new Weather( );
   public final static Weather Sunny = new Weather( );

   static int count = 0;

   Weather( ) {
     System.out.print("c ");
     incr();
   }

   static void incr()
   {
      count++;
   }
 }

您可以看到,count在两个枚举值之后声明,这意味着它在两个值创建之后也被初始化。此外,每个遇到未初始化静态变量的函数调用都将其视为使用默认值进行初始化(对于int而言,它是0)。
因为您在正确初始化count之后从未调用incr,所以您将其值仍然看作0

我同意执行顺序,但在执行此代码时,有一部分让我感到困惑,即在第二次调用时,incr()方法显示计数为“2”。根据您的理论,它应该显示计数为零,不是吗? - kosa
我有点明白了,您能否请更详细地解释一下当Weather()构造函数中遇到incr()时会发生什么?为什么这不会导致某种编译器错误或异常,因为我们正在尝试增加一个尚未初始化的值? - user1500024
在第一次调用incr时,count未初始化,因此该内存位置被分配默认值0。然后它被构造函数递增了2次,然后进行了真正的初始化为0。@thinksteep - Alexander Pogrebnyak
啊!我明白了,经过两次递增之后,“static int count=0”语句执行并将其重新设置为零。有道理。 - kosa
@user1500024 请查看此处的JLS章节:http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.2.3 - Alexander Pogrebnyak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接