有没有办法解决由两个互相引用的枚举引起的类加载问题?

我有两组枚举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

10-08 08:54
查看更多