【问题标题】:Creating new instance of class inside enum constructor when enum is in the class当枚举在类中时,在枚举构造函数中创建类的新实例
【发布时间】:2018-09-14 16:36:47
【问题描述】:

最初我以为我会在这里遇到先有鸡还是先有蛋的问题,但在单元测试中探索这一点并不表示有任何问题。我想了解这里发生了什么。我会认为由于枚举是静态的和最终的,MyEnum 构造函数将在 JVM 加载 MyClass 时运行。但是在我的测试中,它在“MyEnum 构造函数”之前打印“getValue”。

MyClass {

   private enum MyEnum {
       VALUE;

       MyEnum() {
          System.out.println("MyEnum constructor");
          MyClass clazz = new MyClass(); 
       }
   }

   public MyEnum getValue() {
      System.out.println("getValue");
      return MyEnum.VALUE;
   }

}

public class MyClassTest {

    @Test
    public void testStuff() {
        MyClass clazz = new MyClass();
        clazz.getValue();
    }
}

【问题讨论】:

标签: java enums


【解决方案1】:

一个类/接口/枚举/注解嵌套在另一个类中这一事实不会影响其初始化发生的时间。

无论如何,初始化规则都适用。它们在 JLS here 中定义。

一个类或接口类型 T 将在 以下任何一项的第一次出现:

  • T 是一个类,并创建了一个 T 的实例。
  • 调用了由 T 声明的静态方法。
  • 分配了一个由 T 声明的静态字段。
  • 使用了由 T 声明的静态字段,并且该字段不是常量变量(第 4.12.4 节)。

JLS还有says下面关于enum的类型

枚举声明指定一个新的枚举类型,一种特殊的类类型

还有about its members,上面写着

对于在E的声明体中声明的每个枚举常量c, E 有一个隐式声明的 public static final 类型为 E 的字段 与c 同名。该字段有一个变量初始化器 实例化E 并将c 的任何参数传递给所选的构造函数 为E。该字段与c(如果有)具有相同的注释。

把所有这些放在一起,你就会得到对你看到的行为的解释。

您的代码实例化MyClass,然后调用其getValue() 方法。 getValue() 将某些内容打印到标准输出,然后尝试访问由 MyEnum 声明的静态字段。这会触发枚举类型的初始化,该类型初始化 public static static VALUE 字段,该字段调用相应的 MyEnum 构造,该构造再次打印到标准输出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-20
    • 1970-01-01
    • 2011-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多