Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum - static initialization order [duplicate]

Tags:

java

enums

Accessing static variables in constructor of enum class is forbidden in java. Why in enumerations the order of static initialization is not swapped?

Example of correct code:

enum Test
{
    TEST1, TEST2;

    static int x;
}

Why do developers of java did not created such code as correct:

enum Test
{
    static int x;

    TEST1, TEST2;
}

Then static variables could be used in constructor. Now it is forbidden.

Does it have any reason or it is just their design?

like image 968
Pawel Avatar asked Dec 09 '25 23:12

Pawel


2 Answers

Well, it's to ensure safe instance initialization - the enum instances are very similar to static final instances of the enum class, and the language has defined that they be initialized first.

But if you know a trick or two you can effectively use static variables in an enum constructor:

enum Test {
    TEST1, TEST2;

    static class Holder {
        static int x;
    }

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

For more info see Initialization-on-demand holder idiom

like image 152
Bohemian Avatar answered Dec 12 '25 14:12

Bohemian


From JLS (§8.9):

An enum declaration specifies a new enum type


EnumDeclaration: ClassModifiersopt enum Identifier Interfacesopt EnumBody

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


As you can see, the body should be defined with enum-constants declared first and other body declarations may follow - not the other way around!

Further, you don't have to use lazy initialization like bohemian suggested you can do it in a simpler manner. According to JLS you can't do:

enum Test {
    TEST1, TEST2;
    static int x;

    Test(){
        x = 1; // <-- compilation error!
    }
}

but you can use static initializer block:

enum Test {
    TEST1, TEST2;
    static int x;

    static{
        x = 1; // works!
    }
}

The reason that you CAN use the latter is that static declarations are executed in the same order they were declared - assigning x=1 will occur only after x was declared, unlike using a constructor. If you want to verify it - you can add System.out.println() calls to the constructor and static block - you'll see that the constructor is being executed first.

like image 34
Nir Alfasi Avatar answered Dec 12 '25 12:12

Nir Alfasi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!