Есть ли способ обойти проблемы с загрузкой классов, вызванные наличием двух перечислений, которые ссылаются друг на друга?
У меня есть два набора перечислений, 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; он видит Bar.Alpha в конструкторе Foo.A, поэтому он начинает загрузку классов Bar. Он видит ссылку Foo.A в вызове конструктора Bar.Alpha, но (так как мы все еще в конструкторе Foo.A) Foo.A на этом этапе является нулевым, поэтому конструктор Bar.Alpha получает нулевое значение. Если я переверну два цикла for (или иным образом ссылаюсь на Bar перед Foo), выходные данные изменятся так, что все значения Bar будут правильными, а значения Foo - нет.
Есть ли способ обойти это? Я знаю, что могу создать статическую карту и статическую карту в третьем классе, но мне это кажется довольно хакерским. Я также мог бы создать методы Foo.getBar () и Bar.getFoo (), которые ссылаются на внешнюю карту, чтобы он даже не изменил мой интерфейс (реальные классы, в которых я использую инспекторы вместо открытых полей), но он все еще чувствует немного нечист для меня.
(Причина, по которой я делаю это в моей реальной системе: Foo и Bar представляют типы сообщений, которые 2 приложения посылают друг другу; поля Foo.b и Bar.f представляют ожидаемый тип ответа для данного сообщения - поэтому в моем примере кода, когда app_1 получает Foo.A, он должен ответить Bar.Alpha и наоборот.)
Заранее спасибо!