简体   繁体   English

最终私有枚举字段中的循环依赖导致 Null 个值

[英]Cyclic dependency in final private enum fields causes Null values

Consider these enum declarations:考虑这些枚举声明:

enum Color {
    RED(Shape.CIRCLE),
    GREEN(Shape.TRIANGLE),
    BLUE(Shape.SQUARE);

    private final Shape shape;

    Color(Shape shape) {
        this.shape = shape;
    }

    Shape getShape() {
        return shape;
    }
}

enum Shape {
    CIRCLE(Color.RED),
    TRIANGLE(Color.GREEN),
    SQUARE(Color.BLUE);

    private final Color color;

    Shape(Color color) {
        this.color = color;
    }

    Color getColor() {
        return color;
    }
}

There are cyclic dependencies between the enum fields.枚举字段之间存在循环依赖关系。 There are no compiler warnings (using Java 8).没有编译器警告(使用 Java 8)。

However, all these tests will fail in the second line:但是,所有这些测试都将在第二行失败:

@Test
public void testRedAndCircle() {
    assertThat(Color.RED.getShape()).isNotNull();
    assertThat(Shape.CIRCLE.getColor()).isNotNull(); // fails
}

@Test
public void testCircleAndRed() {
    assertThat(Shape.CIRCLE.getColor()).isNotNull();
    assertThat(Color.RED.getShape()).isNotNull(); // fails
}

@Test
public void testGreenAndTriangle() {
    assertThat(Color.GREEN.getShape()).isNotNull();
    assertThat(Shape.TRIANGLE.getColor()).isNotNull(); // fails
}

@Test
public void testBlueAndSquare() {
    assertThat(Color.BLUE.getShape()).isNotNull();
    assertThat(Shape.SQUARE.getColor()).isNotNull(); // fails
}

How can the null value in the enum field be explained? enum字段中的null值怎么解释呢?

It seems that the enum object in the private final fields is not yet completely instantiated.似乎 private final 字段中的枚举 object 尚未完全实例化。

Enum constants are initialized like static fields, so you get a similar outcome as described here .枚举常量的初始化类似于 static 字段,因此您会得到与此处所述类似的结果。 Basically, to initialize one enum correctly, the other already needs to be fully initialized, and vice versa.基本上,要正确初始化一个枚举,另一个枚举已经需要完全初始化,反之亦然。 Obviously, this is a circular dependency and cannot work.显然,这是一个循环依赖,是行不通的。

I would replace one of the getters, eg, the one in Shape with something like this:我会用这样的东西替换其中一个吸气剂,例如Shape中的吸气剂:

Color getColor() {
    for (Color c : Color.values()) {
        if (c.getShape() == this) {
            return c;
        }
    }
    throw new AssertionError();
}

This way, you don't need the color field in Shape and the circular dependency is avoided.这样,您就不需要Shape中的color字段,并且避免了循环依赖。

An added benefit is that the two enums are guaranteed to be consistent.一个额外的好处是保证两个枚举是一致的。 A change in the Color enum will automatically be reflected in Shape . Color枚举中的更改将自动反映在Shape中。

And if you worry about performance ( I wouldn't ), you could also keep the field in Shape and initialize it the first time getColor is called.如果您担心性能(我不会),您也可以将该字段保留在Shape中并在第一次调用getColor时对其进行初始化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM