Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/351.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java圈枚举初始化-发生了什么&;为什么会这样?_Java_Static_Enums_Initialization - Fatal编程技术网

Java圈枚举初始化-发生了什么&;为什么会这样?

Java圈枚举初始化-发生了什么&;为什么会这样?,java,static,enums,initialization,Java,Static,Enums,Initialization,可能重复: 在我们的代码中,我们得到了一些关于枚举的奇怪NPE。当我搜索时,我发现(或多或少)以下情况: public class EnumTest { public static void main(final String[] args){ System.out.println("------ START ----- "); System.out.println("BeezleBubs FOO's rockSteady is: " + BeezleBub.FOO.ro

可能重复:

在我们的代码中,我们得到了一些关于枚举的奇怪NPE。当我搜索时,我发现(或多或少)以下情况:

public class EnumTest {

  public static void main(final String[] args){
    System.out.println("------ START ----- ");
    System.out.println("BeezleBubs FOO's rockSteady is: " + BeezleBub.FOO.rockSteady);
    System.out.println("RockSteady BAR's beezleBub is: " + RockSteady.BAR.beezleBub);
    System.out.println("------  END  ----- ");
  }

  public enum RockSteady {
    BAR(BeezleBub.FOO);

    public final BeezleBub beezleBub;
    private RockSteady(final BeezleBub beezleBub) {
        this.beezleBub = beezleBub;
        System.out.println("Constructing RockSteady, beezleBub = " + beezleBub);
    }

  }

  public enum BeezleBub {

    FOO(RockSteady.BAR);

    public final RockSteady rockSteady;

    private BeezleBub(final RockSteady rockSteady) {
        this.rockSteady = rockSteady;
        System.out.println("Constructing BeezleBub, rockSteady = " + rockSteady);
    }

  }
}
由于某些原因,结果令人尴尬。运行时,此测试输出:

------ START ----- 
Constructing RockSteady, beezleBub = null
Constructing BeezleBub, rockSteady = BAR
BeezleBubs FOO's rockSteady is: BAR
RockSteady BAR's beezleBub is: null
------  END  ----- 
另一件事是,当您切换调用枚举的System.out.prinln()语句时,枚举的初始化也会改变。导致:

------ START ----- 
Constructing BeezleBub, rockSteady = null
Constructing RockSteady, beezleBub = FOO
RockSteady BAR's beezleBub is: FOO
BeezleBubs FOO's rockSteady is: null
------  END  ----- 

有人对发生的事情有清楚的解释吗?它与状态和顺序有关,但我不能完全指出它…

循环依赖性并不酷,我必须承认我还没有生成这样的代码。我可以猜测,实例枚举实例是按需初始化的,而第一个实例pocked提取的最终值仍然为null(final意味着您不能重新分配值,而不是已经分配了值)。当您拨动第二个枚举时,第一个枚举已经创建,并且在Java中一切都按预期工作,类被加载和初始化。这意味着,无论您首先尝试打印哪个类的属性,都会首先加载并初始化。通常,如果类具有相互递归的初始值设定项,那么应该避免在所有构造函数完成之前检查它们的属性

原因很简单,Java没有可以执行的一系列初始化步骤来确保所有可能的使用的原子初始化


顺便说一句,这与枚举无关,它可能发生在普通的旧Java类上。

第一个println语句需要BeezleBub.FOO.rockstable的值。因此,BeezleBub枚举被加载。要初始化BeezleBub FOO实例,它需要加载RockStadible枚举。因此加载RockStable,并将BAR常量初始化为BeezleBub.FOO的当前值,该值仍然为null,因为它正在初始化自身。然后为初始化的BeezleBub.FOO常量分配rockstaid.BAR的值,该值为非null


这是一个有趣的问题,因为这是其中一种情况,其中一个枚举应该是可变的,以便正确初始化。

阅读您的评论让我感到测试用例有些混乱,因为在sysout完成之前调用了BeezleBub.FOO.rockstable。给人的印象是枚举实际上是在其他任何东西之前实例化的…嗯,同意重复…:)Tim链接的dupe有一个类似的解释——听起来都很合乎逻辑:“我理解为什么会发生这种情况——JVM开始类加载Foo;它在Foo.a的构造函数中看到Bar.Alpha,所以它开始类加载Bar.Foo.a在调用Bar.Alpha的构造函数中看到引用,但是(因为我们仍然在Foo.a的构造函数中)此时Foo.A为null,因此Bar.Alpha的构造函数被传递为null。如果我反转两个for循环(或者在Foo之前引用Bar),则输出会更改,从而使Bar的值都正确,但Foo的值不正确。”