Java 枚举:两种枚举类型,每个类型都包含彼此的引用?

2024-01-04

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

我有两组枚举,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 的值则不然。

有什么办法可以解决这个问题吗?我知道我可以在第三个类中创建一个静态映射和一个静态映射,但这对我来说感觉相当黑客。我还可以创建引用外部映射的 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

也可以看看:

  • 覆盖特定枚举的方法 https://stackoverflow.com/a/8615538/1064325
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 枚举:两种枚举类型,每个类型都包含彼此的引用? 的相关文章

随机推荐