有没有办法解决由两个互相引用的枚举引起的类加载问题?
我有两组枚举Foo和Bar,它们的定义如下:
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进行类加载;它在Foo.A的构造函数中看到Bar.Alpha,因此它开始类加载Bar。它在对Bar.Alpha的构造函数的调用中看到Foo.A引用,但是(由于我们仍在Foo.A的构造函数中)Foo.A此时为null,因此Bar.Alpha的构造函数传递了null。如果我颠倒了两个for循环(或在Foo之前引用Bar),则输出将更改,以使Bar的值都正确,而Foo的值则不正确。
有什么办法可以解决这个问题?我知道我可以在第3类中创建一个静态地图和一个静态地图,但是这对我来说确实有点不足。我还可以使Foo.getBar()和Bar.getFoo()方法引用外部地图,因此它甚至都不会更改我的界面(我使用的实际类是检查器,而不是公共字段),但仍然感觉对我来说有点不干净
(我在实际系统中执行此操作的原因:Foo和Bar代表2个应用相互发送的消息类型; Foo.b和Bar.f字段代表给定消息的预期响应类型-因此在我的系统中示例代码,当app_1收到Foo.A时,需要使用Bar.Alpha进行回复,反之亦然。)
提前致谢!
最佳答案
最好的方法之一是使用枚举多态技术:
public class EnumTest {
public enum Foo {
A {
@Override
public Bar getBar() {
return Bar.Alpha;
}
},
B {
@Override
public Bar getBar() {
return Bar.Delta;
}
},
C {
@Override
public Bar getBar() {
return Bar.Alpha;
}
},
;
public abstract Bar getBar();
}
public enum Bar {
Alpha {
@Override
public Foo getFoo() {
return Foo.A;
}
},
Beta {
@Override
public Foo getFoo() {
return Foo.C;
}
},
Delta {
@Override
public Foo getFoo() {
return Foo.C;
}
},
;
public abstract Foo getFoo();
}
public static void main(String[] args) {
for (Foo f : Foo.values()) {
System.out.println(f + " bar " + f.getBar());
}
for (Bar b : Bar.values()) {
System.out.println(b + " foo " + b.getFoo());
}
}
}
上面的代码产生所需的输出:
A bar Alpha
B bar Delta
C bar Alpha
Alpha foo A
Beta foo C
Delta foo C
也可以看看:
Overridding method of a specific enum