Java Cyclomatic Enum初始化 - 会发生什么&为什么会这样?

时间:2011-11-10 08:13:37

标签: java static enums initialization

  

可能重复:
  Java Enums: Two enum types, each containing references to each other?

在我们的代码中,我们得到了一些关于Enums的奇怪的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  ----- 

另一件事是当你切换调用Enums的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  ----- 

任何人都清楚地解释了发生了什么?它与国家和地区有关。订单,但我不能完全指责它......

3 个答案:

答案 0 :(得分:2)

在Java中,类被加载并初始化为惰性。这意味着,首先尝试打印的任何类的属性都会被加载并初始化。通常,如果你有相互递归的类初始化器,那么你应该避免在所有构造函数完成之前检查它们的属性。

原因很简单,Java没有执行初始化步骤序列,这将确保所有可能用途的原子初始化。

顺便说一句,这与简单的旧Java类可能会发生的枚举无关。

答案 1 :(得分:0)

循环依赖并不酷,我必须承认我还没有生成这样的代码。我可以猜测,实例枚举实例按需初始化,并且第一个实例pocked拉出最终值仍然为空(最终意味着您不能重新分配值,而不是已经分配了)。当您点击第二个枚举时,第一个已经创建并且eveything按预期工作

答案 2 :(得分:0)

第一个println语句需要BeezleBub.FOO.rockSteady的值。所以BeezleBub枚举已加载。要初始化BeezleBub FOO实例,需要加载RockSteady枚举。因此RockSteady被加载,并且BAR常量被初始化为BeezleBub.FOO的当前值,因为它正在初始化自身的过程中仍然是null。然后为初始化的BeezleBub.FOO常量赋予RockSteady.BAR的值,该值为非null。

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