簡體   English   中英

最終私有枚舉字段中的循環依賴導致 Null 個值

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

考慮這些枚舉聲明:

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;
    }
}

枚舉字段之間存在循環依賴關系。 沒有編譯器警告(使用 Java 8)。

但是,所有這些測試都將在第二行失敗:

@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
}

enum字段中的null值怎么解釋呢?

似乎 private final 字段中的枚舉 object 尚未完全實例化。

枚舉常量的初始化類似於 static 字段,因此您會得到與此處所述類似的結果。 基本上,要正確初始化一個枚舉,另一個枚舉已經需要完全初始化,反之亦然。 顯然,這是一個循環依賴,是行不通的。

我會用這樣的東西替換其中一個吸氣劑,例如Shape中的吸氣劑:

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

這樣,您就不需要Shape中的color字段,並且避免了循環依賴。

一個額外的好處是保證兩個枚舉是一致的。 Color枚舉中的更改將自動反映在Shape中。

如果您擔心性能(我不會),您也可以將該字段保留在Shape中並在第一次調用getColor時對其進行初始化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM