2012-07-20 111 views
3

我发现它带有枚举的凝灰岩。这是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吗? 基于此,我将count变量修改为static。 但是我看到的是这样的: 编译时间错误:非法引用来自初始值设定项的静态字段。

在网上搜索我发现这是Sun的一种循环漏洞,它允许可以改变静态字段的静态方法。好吧..所以现在我用一个静态方法增加我的工作:

​​

令我惊讶的是,我得到的输出:c c 0 0! 任何人都可以在拍摄自己之前向我解释这种行为吗?

+0

请解决您的缩进和括号。 – ardent 2012-07-20 16:35:17

+0

非常凝灰岩的问题!所有的Java程序员,自己装甲:) – Kameron 2012-07-20 16:36:12

+0

ardentsonata:好的 – user1500024 2012-07-20 16:36:50

回答

5

枚举值可以被认为是荣耀的静态字段(它们在下面)。

因此,如果您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

+0

我同意执行的顺序,但是执行这个代码时我的一部分困惑是在第二次调用时,incr()方法显示计数为'2'。根据你的理论,它应该显示计数为零,不是吗? – kosa 2012-07-20 16:49:52

+0

我部分清楚;你能解释一下在Weather()构造函数中遇到incr()时会发生什么吗?为什么它不会导致某种编译器错误或异常,因为我们试图增加一个尚未初始化的值? – user1500024 2012-07-20 16:51:27

+0

@thinksteep。在第一次调用'incr''' count'时,初始化,所以内存位置的默认值为'0'。然后它由构造函数递增2次,然后发生REAL初始化为'0'。 – 2012-07-20 16:52:28