[英]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.