为什么枚举构造函数无法访问静态字段

2022-09-02 14:01:35

可能的重复:
为什么枚举的构造函数无法访问静态字段?

enum Test {
  e1,e2;      

  int i=0;
  static int j=5;

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

在上面的代码中,构造函数可以访问实例变量,但不能访问静态变量 J。

我读过的答案与其他作者有关,都说e1和e2在初始化之前初始化了J(静态字段),但是根据java规范,所有静态字段在将类加载到内存时都会初始化,即在构造函数运行之前。因此,在运行 Test() 构造函数之前,必须初始化静态变量 j。我无法理解限制,任何身体都可以让我理解。我已经阅读了问题的答案 为什么枚举的构造函数不能访问静态字段?但是我对这样的答案不满意:-构造函数在静态字段全部初始化之前被调用。

假设如果用一个简单的类(如枚举)举另一个例子

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

如果你想象一下你的枚举作为一个类的实际外观,这是有道理的:

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

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


答案 2

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

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

为什么会这样只能回答几个人(例如。Josh Bloch和Neal Gafter在javadoc中被描述为Enum的作者,也许还有一些不知名的其他人)