2012-11-23 39 views
17

可能重复:
Why can’t enum’s constructor access static fields?为什么枚举构造函数不能访问静态字段

enum Test { 
    e1,e2;  

    int i=0; 
    static int j=5; 

    Test(){ 
    System.out.println(i+" "+j); 
    } 
} 

在上面的代码构造函数可以访问实例变量而不是静态变量J

我已经阅读了与其他作者有关的答案都说e1和e2在初始化J(静态字段)之前初始化,但是根据java spec所有静态字段 初始化的时候曾经把类加载到内存中,也就是在构造函数运行之前。 所以在运行Test()构造函数之前,必须初始化静态变量j。我无法理解限制,任何机构都可以让我理解。我已经阅读了问题的答案Why can't enum's constructor access static fields?但我不满意如下答案: - 在静态字段全部被初始化之前调用构造函数。

想,如果采取与一个简单的类象枚举另一个例子

class Test{ 
    public static final Test t=new Test(); 
    static int a=5; 

    Test(){ 
    System.out.println(a); 
    } 

    public static void main(String[] args) { 
    } 
} 

这里根据有参数的构造将静态字段的初始化之前运行,它也运行,因为它是印刷0(由于JVM做了动初始化)。但没有编译错误或没有运行时问题。那么为什么同样的事情不会发生在枚举上。

+1

其实很好的问题,我不明白为什么这是。可能与Java编译器如何编译类文件有关。 – Gerbrand

+1

我不是java专家,但不是枚举的成员('e1'和'e2'上面)基本上是'enum'的静态成员?因此,当*他们*被初始化为值时,必须调用构造函数。但'j'不会被初始化? –

+0

Java中的每个枚举类似*扩展java.lang.Enum类的类。这个'java.lang.Enum'不能被其他的* normal *类扩展。 所以,你的论点“像枚举一样简单的类”产生预期的输出是无效的。 – Prasanth

回答

2

问题是,枚举的实例是在静态字段初始化期间创建的。他们在你的静态字段初始化之前创建。 它们必须处于静态数组值并且可以静态访问,所以它是有道理的。正如在anser中为“为什么enum的构造函数不能访问静态字段?”所述,它不幸的是,这发生在所有用户定义的静态字段初始化之前。 但是如果它被交换了,你不能在静态初始化中访问枚举实例,所以它需要在创建枚举值之前和之后允许静态块。

我不知道是否问题是因为枚举值的初始化是Enum类的关注(并且由JVM处理(此逻辑不在Enum类本身中),或者因为您无法在枚举值之前放置静态字段。

为什么它是这样可以回答只有少数人(如乔希布洛赫和Neal Gafter谁被表述为在Javadoc枚举的作者,也许有些未知的人)

6

如果你想象有你的枚举实际上看起来像一类,它是有道理的:

public class Test { 
    // Imagine you cannot move these two statements: 
    public static final Test e1 = new Test(); 
    public static final Test e2 = new Test(); 

    int i=0; 
    static int j=5; 

    private Test(){ 
    System.out.println(i+ " " + j); 
    } 

    static int getJ() { 
    return j; 
    } 


    public static void main(String[] args) { 
    System.out.println(Test.getJ()); 
    } 
} 

此打印:

0 0 
0 0 
5 

如果你可以分享一个具体的例子(而不是理论上的),我们可以建议如何重新设计代码,以达到预期的效果,尽管静态字段限制。

相关问题