枚举 - 静态初始化顺序



java中禁止访问enum类的构造函数中的static变量。为什么在枚举中不交换静态初始化的顺序?

正确代码示例:

enum Test
{
    TEST1, TEST2;
    static int x;
}

为什么Java的开发人员没有创建正确的代码:

enum Test
{
    static int x;
    TEST1, TEST2;
}

然后static变量可以在构造函数中使用。现在它是被禁止的。

它有任何理由还是只是他们的设计?

嗯,这是为了确保安全的实例初始化 - 枚举实例与枚举类的static final实例非常相似,并且语言已经定义了它们首先初始化。

但是,如果您知道一两个技巧,则可以在枚举构造函数中有效地使用静态变量:

enum Test {
    TEST1, TEST2;
    static class Holder {
        static int x;
    }
    Test() {
        Holder.x++; // no compiler error
    }
}

有关详细信息,请参阅按需初始化持有者习惯用法

来自 JLS (§8.9):

枚举

声明指定新的枚举类型


枚举声明: ClassModifiersopt enum Identifier Interfacesopt EnumBody

EnumBody: { EnumConstants-opt ,opt EnumBodyDeclarations-opt }


如您所见,主体应该首先声明枚举常量来定义,其他主体声明可能会随之而来 - 而不是相反!

此外,您不必像波西米亚建议的那样使用延迟初始化,您可以以更简单的方式进行初始化。根据JLS你不能做:

enum Test {
    TEST1, TEST2;
    static int x;
    Test(){
        x = 1; // <-- compilation error!
    }
}

但您可以使用静态初始值设定项块:

enum Test {
    TEST1, TEST2;
    static int x;
    static{
        x = 1; // works!
    }
}

您可以使用后者的原因是静态声明的执行顺序与声明顺序相同 - 分配x=1仅在声明x后发生,这与使用构造函数不同。如果要验证它 - 可以向构造函数和静态块添加System.out.println()调用 - 您将看到构造函数首先被执行。

最新更新