为什么枚举构造函数不能访问静态字段

时间:2012-11-23 07:54:22

标签: java enums

  

可能重复:
  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规范所有的静态字段 当类加载到内存时,即在运行构造函数之前初始化。 因此,在运行Test()构造函数之前,必须初始化静态变量j。我无法理解限制,任何机构都能让我理解。我已经阅读了问题的答案Why can't enum's constructor access static fields?但我对答案不满意如下: - 构造函数在静态字段全部被调用之前被调用已初始化。

假设用另一个像enum

这样的简单类的例子
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进行了初始化)。但没有编译错误或没有运行时问题。那么为什么枚举不会发生同样的事情。

2 个答案:

答案 0 :(得分: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

如果你可以分享一个具体的例子(而不是理论上的例子),我们可以建议如何重新设计代码以实现所需的结果,尽管存在静态字段限制。

答案 1 :(得分:2)

问题是,枚举的实例是在静态字段的实际化过程中创建的。他们在静态字段初始化之前创建。 它们必须是静态数组值并且可以静态访问,因此它是有意义的。正如anser to"为什么不能使用构造函数访问静态字段?",不幸的是,这发生在所有用户定义的静态字段inicialization之前。 但如果它被交换,则无法在静态初始化中访问枚举实例,因此在创建枚举值之前和之后都需要允许静态块。

我不知道问题是因为枚举值的内在化是Enum类的关注(并且由JVM专门处理(这个逻辑不在Enum类本身中),或者因为你不能在枚举值之前放置静态字段

为什么这样才能回答很少的人(例如Josh Bloch和Neal Gafter在javadoc中被称为Enum的作者,也许还有一些不为人知的人)