Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the Java enum constants initialization is not complete?

Tags:

java

enums

I stumbled upon a very weird bug and I can't explain why it happens. Imagine the following enum:

import java.awt.Color;

public class test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        System.out.println(MyEnum.CONSTANT1.get());
        System.out.println(MyEnum.CONSTANT2.get());
    }

    private enum MyEnum {
        CONSTANT1(staticMethod1()),
        CONSTANT2(staticMethod2());

        private static final Color WHY_AM_I_NULL = new Color(255, 255, 255);

        private final Color color;

        private MyEnum(Color color) {
            this.color = color;
        }

        public Color get() {
            return color;
        }

        private static Color staticMethod1() {
            return new Color(100, 100, 100);
        }

        private static Color staticMethod2() {
            return WHY_AM_I_NULL;
        }
    }

}

The results when you run this are:

java.awt.Color[r=100,g=100,b=100]
null

The question is, why the second one is null?

Ammendment: If you put the WHY_AM_I_NULL in a private static class inside the enum, then it is initialized first.

like image 392
m_pGladiator Avatar asked Aug 25 '11 09:08

m_pGladiator


2 Answers

The problem is that all static fields (and enum instances count as such) are initialized in their declared order (specification). So when CONSTANT2 is instantiated, the field WHY_AM_I_NULL is still not initialized (and therefore null).

As you can't put the field before the enum instances, you have to find some other way of doing what you want (e.g., putting the field outside the enum class). If you tell us, what you really want to accomplish, one could make further suggestions.

Edit: If you put WHY_AM_I_NULL in a nested class, the fields of this class will be initialized as soon as the class is first accessed (i.e., in this case during the execution of staticMethod2).

like image 91
Philipp Wendler Avatar answered Sep 28 '22 06:09

Philipp Wendler


Enums are the compiler feature. Actually compiler creates class named MyEnum that contains 2 public static fields CONSTANT1 and CONSTANT2 and other code.

Static initialization is done up-to-down, so the CONSTANT2 is created and is initialized before static variable WHY_AM_I_NULL. This is why WHY_AM_I_NULL is null when CONSTANT2 is being initialized.

like image 41
AlexR Avatar answered Sep 28 '22 06:09

AlexR