当前位置: 首页 > 面试题库 >

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

程鸿煊
2023-03-14
问题内容

有没有一种方法可以解决由两个互相引用的枚举引起的类加载问题?

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

也可以看看:

  • 特定枚举的覆盖方法


 类似资料:
  • 问题内容: 例如,我该怎么做: 结果示例: 问题答案: 迅捷4.2+ 从Swift 4.2(使用Xcode 10)开始,只需添加协议一致性即可从中受益。要添加此协议一致性,您只需要在某处写: 如果枚举是您自己的,则可以直接在声明中指定一致性: 然后,以下代码将打印所有可能的值: 与早期Swift版本(3.x和4.x)的兼容性 如果您需要支持Swift 3.x或4.0,则可以通过添加以下代码来模仿S

  • 问题内容: 我有一个枚举的类对象(我有一个),我需要获取此枚举表示的枚举值的列表。该静态函数有我需要什么,但我不知道怎么去从类对象访问它。 问题答案:

  • 例如,我如何做类似的事情: 结果示例:

  • 枚举类型(也可以称为“枚举器”)由一组具有独立标识符(名称)的整数类型常量构成,在 C# 中枚举类型不仅可以在类或结构体的内部声明,也可以在类或结构体的外部声明,默认情况下枚举类型中成员的默认值是从 0 开始的,然后逐一递增。 在 C# 中可以使用 enum 关键字来声明枚举类型,语法格式如下所示: enum enum_name{     enumeration list; } 其中,enum_n

  • 枚举是为了让程序可读性更好,比如用来描述用户的角色,普通的会员、付费的会员等,同时也限定了用户角色的种类,保证安全性,不会出现上帝角色这种乱入的东西。 枚举的类别与写法 默认值从0开始,依次递增,这个你应该还记得。 普通的枚举 let str = 'something' enum test{ test01, } enum FileAccess { None, Read