有沒有辦法避免由兩個相互引用的枚舉引起的類加載問題?Java枚舉:兩個枚舉類型,每個枚舉類型包含彼此的引用?
我有兩套枚舉,Foo和酒吧的,像這樣定義的:
public class EnumTest {
public enum Foo {
A(Bar.Alpha),
B(Bar.Delta),
C(Bar.Alpha);
private Foo(Bar b) {
this.b = b;
}
public final Bar b;
}
public enum Bar {
Alpha(Foo.A),
Beta(Foo.C),
Delta(Foo.C);
private Bar(Foo f) {
this.f = f;
}
public final Foo f;
}
public static void main (String[] args) {
for (Foo f: Foo.values()) {
System.out.println(f + " bar " + f.b);
}
for (Bar b: Bar.values()) {
System.out.println(b + " foo " + b.f);
}
}
}
以上代碼生成的輸出:
A bar Alpha
B bar Delta
C bar Alpha
Alpha foo null
Beta foo null
Delta foo null
我明白爲什麼會發生 - 在JVM啓動類加載富;它看到Foo.A的構造函數中的Bar.Alpha,因此它開始加載Bar。它在調用Bar.Alpha的構造函數時看到Foo.A引用,但是(因爲我們仍然在Foo.A的構造函數中)Foo.A此時爲null,因此Bar.Alpha的構造函數會傳遞一個null。如果我將兩個for循環倒轉(或者在Foo之前引用Bar),則輸出會發生變化,以便Bar的值全部正確,但Foo的值不正確。
有什麼辦法可以解決這個問題嗎?我知道我可以在第三堂課創建一個靜態地圖和一個靜態地圖,但是這對我來說感覺相當不好。我也可以創建引用外部映射的Foo.getBar()和Bar.getFoo()方法,所以它甚至不會改變我的界面(實際的類我使用檢查器而不是公共字段),但它仍然感覺對我不潔。我在我的實際系統中這樣做的原因:Foo和Bar表示兩個應用程序相互發送的消息類型; Foo.b和Bar.f字段表示給定消息的預期響應類型 - 所以在我的示例代碼中,當app_1收到Foo.A時,它需要使用Bar.Alpha進行回覆,反之亦然。)
在此先感謝!
對我來說似乎過於複雜。 @維基的回答更清潔,海事組織。爲什麼這種方法更好(你說「最好」)? – 2015-05-19 15:26:23
@NoamNelke我已經投了韋基的方法,這很有趣。儘管我個人認爲它的建議方式要好得多,因爲循環引用在它的枚舉範圍內,我們的答案之間的一個很大的區別是,在返回之前,我可以在返回之前執行任何運行時邏輯,例如: '公共酒吧getBar(布爾nullIfAlpha){返回nullIfAlpha? null:Bar.Alpha; }'。無論如何,我已經將我的答案編輯爲「最好的」之一,因爲它可能是基於意見的。感謝您的回覆! – falsarella 2015-05-19 17:29:38