Java 枚举:两种枚举类型,每个类型都包含对彼此的引用? [英] Java Enums: Two enum types, each containing references to each other?

查看:18
本文介绍了Java 枚举:两种枚举类型,每个类型都包含对彼此的引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is there a way to get around the class-loading issues caused by having two enums that reference each other?

我有两组枚举,Foo 和 Bar,定义如下:

I have two sets of enumerations, Foo and Bar, defined like so:

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);
    }
  }
}

以上代码作为输出产生:

The above code produces as output:

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 为空,因此 Bar.Alpha 的构造函数被传递一个空值.如果我反转两个 for 循环(或者在 Foo 之前引用 Bar),输出会发生变化,所以 Bar 的值都是正确的,但 Foo 的值不是.

I understand why it happens - the JVM starts classloading Foo; it sees the Bar.Alpha in Foo.A's constructor, so it starts classloading Bar. It sees the Foo.A reference in the call to Bar.Alpha's constructor, but (since we're still in Foo.A's constructor) Foo.A is null at this point, so Bar.Alpha's constructor gets passed a null. If I reverse the two for loops (or otherwise reference Bar before Foo), the output changes so that Bar's values are all correct, but Foo's values are not.

有什么办法可以解决这个问题吗?我知道我可以在第三堂课中创建一个静态地图和一个静态地图,但这对我来说感觉相当黑客.我还可以创建引用外部映射的 Foo.getBar() 和 Bar.getFoo() 方法,因此它甚至不会改变我的界面(我使用的实际类使用检查器而不是公共字段),但它仍然感觉对我来说有点不干净.

Is there any way to get around this? I know I can create a static Map and a static Map in a 3rd class, but that feels fairly hackish to me. I could also make Foo.getBar() and Bar.getFoo() methods that refer to the external map, so it wouldn't even change my interface (the actual classes I have use inspectors instead of public fields), but it still feels kind of unclean to me.

(我在实际系统中这样做的原因:Foo 和 Bar 表示两个应用程序相互发送的消息类型;Foo.b 和 Bar.f 字段表示给定消息的预期响应类型 -所以在我的示例代码中,当 app_1 收到一个 Foo.A 时,它需要回复一个 Bar.Alpha,反之亦然.)

(The reason I'm doing this in my actual system: Foo and Bar represent types of messages that 2 apps send to each other; the Foo.b and Bar.f fields represent the expected response type for a given message - so in my sample code, when app_1 receives a Foo.A, it needs to reply with a Bar.Alpha and vice-versa.)

提前致谢!

推荐答案

最好的方法之一是使用枚举多态技术:

One of the best ways would be using the enum polymorphism technique:

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());
        }
    }
}

上面的代码产生你想要的输出:

The above code produces the output you want:

A bar Alpha
B bar Delta
C bar Alpha
Alpha foo A
Beta foo C
Delta foo C

另见:

这篇关于Java 枚举:两种枚举类型,每个类型都包含对彼此的引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆