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

Kru*_*hna 18 java enums

可能重复:
为什么enum的构造函数不能访问静态字段?

enum Test {
  e1,e2;      

  int i=0;
  static int j=5;

  Test(){
    System.out.println(i+" "+j);
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

假设是用另一个像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) {
  }
}
Run Code Online (Sandbox Code Playgroud)

根据那里的参数,构造函数将在静态字段的初始化之前运行,并且它也在运行时因为它的打印0(因为JVM进行了初始化).但没有编译错误或没有运行时问题.那么为什么枚举不会发生同样的事情.

Dun*_*nes 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());
  }
}
Run Code Online (Sandbox Code Playgroud)

这打印:

0 0
0 0
5
Run Code Online (Sandbox Code Playgroud)

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


Alp*_*dar 3

问题是,枚举实例是在静态字段初始化期间创建的。它们是在静态字段初始化之前创建的。它们必须位于静态数组值中并且可以静态访问,因此这是有意义的。正如“为什么枚举的构造函数不能访问静态字段?”中所述,不幸的是,这种情况发生在所有用户定义的静态字段初始化之前。但如果它被交换,您将无法在静态初始化中访问枚举实例,因此需要在创建枚举值之前和之后都允许静态块。

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

为什么是这种方式只能回答少数人(例如 Josh Bloch 和 Neal Gafter 在 javadoc 中被称为 Enum 的作者,也许还有一些不知名的其他人)