枚举 - 静态初始化顺序

时间:2013-10-20 23:36:55

标签: java enums

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

正确代码示例:

enum Test
{
    TEST1, TEST2;

    static int x;
}

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

enum Test
{
    static int x;

    TEST1, TEST2;
}

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

是否有任何理由或仅仅是他们的设计?

2 个答案:

答案 0 :(得分:4)

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

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

enum Test {
    TEST1, TEST2;

    static class Holder {
        static int x;
    }

    Test() {
        Holder.x++; // no compiler error
    }
}

有关详细信息,请参阅Initialization-on-demand holder idiom

答案 1 :(得分:1)

来自JLS (§8.9)

  

枚举声明指定新的枚举类型

     
     

EnumDeclaration:       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()调用 - 您将看到构造函数首先被执行。