【问题标题】:Why enum constructor can't access static field [duplicate]为什么枚举构造函数无法访问静态字段[重复]
【发布时间】:2012-11-23 07:54:22
【问题描述】:

可能重复:
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。

我已经阅读了与其他作者相关的答案都说在初始化 J(静态字段)之前初始化了 e1 和 e2,但是根据 java 规范所有的静态字段 当类加载到内存时初始化,即在构造函数运行之前。 因此,在运行 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 所做的初始化一样)。但是没有编译错误或没有运行时问题。那么为什么枚举不会发生同样的事情呢。

【问题讨论】:

  • 其实是个好问题,我不知道为什么会这样。可能与 Java 编译器如何编译类文件有关。
  • 我不是 java 专家,但不是枚举成员(e1e2 以上)本质上是enum 的静态成员吗​​?因此,当 它们 用值初始化时,必须调用构造函数。但是j 还没有初始化?
  • Java 中的每个枚举就像一个扩展java.lang.Enum 的类。这个java.lang.Enum 不能被其他normal 类扩展。因此,您关于“像枚举这样的简单类”产生预期输出的论点是无效的。
  • My answer to this other question 可能有助于进一步阐明这一点。
  • @ Damien_The_Unbeliever 是的 e1 和 e2 是 public static 和 final 所以初始化构造函数需要调用,但是如果你用一个简单的类测试同样的东西,你可以看到在运行构造函数之前JVM初始化为0的值然后是什么问题,为什么限制枚举

标签: java enums


【解决方案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】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2010-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-03
      • 2011-05-15
      • 1970-01-01
      • 2013-12-28
      • 2014-06-01
      相关资源
      最近更新 更多