19

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

enum Test {
  e1,e2;      

  int i=0;
  static int j=5;

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

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

我已经阅读了与其他作者相关的答案,所有人都说在初始化 J(静态字段)之前初始化了 e1 和 e2,但是根据 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 进行了初始化)。但是没有编译错误或没有运行时问题。那么为什么枚举不会发生同样的事情。

4

2 回答 2

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

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

于 2012-11-23T09:00:41.417 回答
3

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

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

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

于 2012-11-23T08:30:38.337 回答