有没有办法避免由两个相互引用的枚举引起的类加载问题?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