Java 如何创建循环枚举定义?

Java 如何创建循环枚举定义?,java,Java,我正在尝试创建这两个枚举类 import static B.B1; public enum A { A1(B1); private A(B b) { System.out.println(b); } } 但是当我运行这个代码时 public class Main { public static void main(String[] args) { A1.ordinal(); } } 我得到以下输出 nul

我正在尝试创建这两个枚举类

import static B.B1;

public enum A {
    
    A1(B1);

    private A(B b) {
        System.out.println(b);
    }
}
但是当我运行这个代码时

public class Main {

    public static void main(String[] args) {
        A1.ordinal();
    }
}
我得到以下输出

null
B1
而不是

A1
B1

我如何解决这个问题?

你不能在构造函数内部解决这个问题。这是类初始化方式的一个基本限制:如果一个类在初始化过程中循环引用自己,它会看到类的当前状态,这可能意味着可以观察到
final
字段为
null
,即使以后可以将它们视为非null

相反,您可以在枚举上使用一个方法来获取“其他”:


现在,
A1.other()
将为您提供
B1
;而
B1.other()
将为您提供
A1

您无法在构造函数中解决此问题。这是类初始化方式的一个基本限制:如果一个类在初始化过程中循环引用自己,它会看到类的当前状态,这可能意味着可以观察到
final
字段为
null
,即使以后可以将它们视为非null

相反,您可以在枚举上使用一个方法来获取“其他”:


现在,
A1.other()
将为您提供
B1
;而
B1.other()
将为您提供
A1

“我如何解决这个问题?”您试图用这个实现什么?这让我感到惊讶。我知道这与初始化顺序有关,但在我看来,输出取决于调用方首先引用了A和B中的哪一个,这似乎有点不确定。如果我切换到
B1.ordinal()
在main函数中,将输出更改为
null A1
@marstran enum(大多数情况下)只是公共静态最终实例的语法糖。如果一个实例在初始化过程中引用了另一个类,则另一个类将开始初始化;如果另一个类引用回第一个类,则类装入器无法再次开始初始化第一个类,因此它有两个选项:抛出异常,或继续,允许第二个类观察第一个类的当前(尽管不是最终)状态。我想说一个例外会更好,但Java不是这样做的。@AndyTurner对,同意。或者甚至是编译错误(虽然我猜编译器无法找到任意大小的所有循环)。另一种方法是延迟构造以保存关联,而不是使用枚举中的构造函数和字段来定义关联。“我如何解决此问题?”你想用这个做什么?这让我很惊讶。我知道这与初始化顺序有关,但在我看来,输出取决于调用方首先引用了A和B中的哪一个,这似乎有点不确定。如果我切换到
B1.ordinal()
在main函数中,将输出更改为
null A1
@marstran enum(大多数情况下)只是公共静态最终实例的语法糖。如果一个实例在初始化过程中引用了另一个类,则另一个类将开始初始化;如果另一个类引用回第一个类,则类装入器无法再次开始初始化第一个类,因此它有两个选项:抛出异常,或继续,允许第二个类观察第一个类的当前(尽管不是最终)状态。我想说一个例外会更好,但Java不是这样做的。@AndyTurner对,同意。或者甚至是编译错误(虽然我猜编译器无法找到任意大小的所有循环)。另一种方法是延迟构造以保存关联,而不是使用枚举中的构造函数和字段来定义关联。此外,如果需要为每个枚举成员返回不同的实例,您可以在枚举上创建一个抽象方法,然后在每个枚举成员上实现它。如果
other
函数的主体包含对枚举变量的大量处理,我如何避免在每次调用
other
函数时重新执行它?@Subia您不应该在枚举的方法中执行非常繁重的处理。简单地说,您可以将“重”值缓存在某种外部映射中。此外,如果需要为每个枚举成员返回不同的实例,可以在枚举上创建一个抽象方法,然后在每个枚举成员上实现它。如果
other
函数的主体包含对枚举变量的大量处理,我如何避免在每次调用
other
函数时重新执行它?@Subia您不应该在枚举的方法中进行非常繁重的处理。简单地说,您可以将“重”值缓存在某种外部映射中。
A1
B1
public enum A {
    A1;

    B other() { return B.B1; }
}

public enum B {
    B1;

    A other() { return A.A1; }
}