Sbo*_*odd 31 java oop enums classloader cyclic-reference
有没有办法解决因两个相互引用的枚举导致的类加载问题?
我有两组枚举,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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码产生输出:
A bar Alpha
B bar Delta
C bar Alpha
Alpha foo null
Beta foo null
Delta foo null
Run Code Online (Sandbox Code Playgroud)
我理解为什么会这样--JVM开始加载Foo; 它在Foo.A的构造函数中看到了Bar.Alpha,因此它开始加载Bar的类.它在调用Bar.Alpha的构造函数时看到了Foo.A引用,但是(因为我们仍然在Foo.A的构造函数中)此时Foo.A为null,因此Bar.Alpha的构造函数被传递为null.如果我反转两个for循环(或者在Foo之前引用Bar),输出会改变,因此Bar的值都是正确的,但是Foo的值不是.
有没有办法解决这个问题?我知道我可以在第三类中创建一个静态Map和一个静态Map,但这对我来说是相当的hackish.我也可以制作引用外部地图的Foo.getBar()和Bar.getFoo()方法,所以它甚至不会改变我的界面(我使用检查员而不是公共字段的实际类),但它仍然感觉对我来说有点不洁净.
(我在实际系统中这样做的原因是:Foo和Bar代表2个应用程序相互发送的消息类型; Foo.b和Bar.f字段代表给定消息的预期响应类型 - 所以在我的示例代码,当app_1收到Foo.A时,它需要使用Bar.Alpha回复,反之亦然.)
提前致谢!
fal*_*lla 22
最好的方法之一是使用枚举多态技术:
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());
}
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码生成了你想要的输出:
A bar Alpha
B bar Delta
C bar Alpha
Alpha foo A
Beta foo C
Delta foo C
Run Code Online (Sandbox Code Playgroud)
也可以看看:
wei*_*iji 11
问题不在于"两个枚举相互引用",而是"两个枚举在其构造函数中相互引用".这个循环引用是棘手的部分.
使用Foo.setResponse(Bar b)和Bar.setResponse(Foo f)方法怎么样?不是在Foo构造函数中设置Foo的Bar(而类似于Bar构造函数中的Bar的Foo),而是使用方法进行初始化?例如:
富:
public enum Foo {
A, B, C;
private void setResponse(Bar b) {
this.b = b;
}
private Bar b;
public Bar getB() {
return b;
}
static {
A.setResponse(Bar.Alpha);
B.setResponse(Bar.Delta);
C.setResponse(Bar.Alpha);
}
}
Run Code Online (Sandbox Code Playgroud)
酒吧:
public enum Bar {
Alpha, Beta, Delta;
private void setResponse(Foo f) {
this.f = f;
}
private Foo f;
public Foo getF() {
return f;
}
static {
Alpha.setResponse(Foo.A);
Beta.setResponse(Foo.C);
Delta.setResponse(Foo.C);
}
}
Run Code Online (Sandbox Code Playgroud)
另外,你提到Foo和Bar是两种类型的消息.是否可以将它们组合成一种类型?从我所看到的,他们在这里的行为是一样的.这不能解决循环逻辑问题,但它可能会让您对设计有所了解......
| 归档时间: |
|
| 查看次数: |
17434 次 |
| 最近记录: |