Execution order of of static blocks in an Enum type w.r.t to constructor

This is from Effective Java :

// Implementing a fromString method on an enum type
  private static final Map<String, Operation> stringToEnum
      = new HashMap<String, Operation>();

  static { // Initialize map from constant name to enum constant
    for (Operation op : values())
      stringToEnum.put(op.toString(), op);
  }

  // Returns Operation for string, or null if string is invalid
  public static Operation fromString(String symbol) {
    return stringToEnum.get(symbol);
  }

Note that the Operation constants are put into the stringToEnum map from a static block that runs after the constants have been created. Trying to make each constant put itself into the map from its own constructor would cause a compilation error. This is a good thing, because it would cause a NullPointerException if it were legal. Enum constructors aren't permitted to access the enum's static fields, except for compile-time constant fields. This restriction is necessary because these static fields have not yet been initialized when the constructors run.

My question is regarding the line :

"Note that the Operation constants are put into the stringToEnum map from a static block that runs after the constants have been created" .

I thought the static block gets executed before the constructor runs. The are actually executed during class load time.

What am I missing here ?


I understand your question as: why is there a guarantee that the enum constants will be initialised before the static block is run. The answer is given in the JLS, and a specific example is given in #8.9.2.1, with the following explanation:

static initialization occurs top to bottom.

and the enums constants are implicitly final static and are declared before the static initializer block.

EDIT

The behaviour is not different from a normal class. The code below prints:

In constructor: PLUS
PLUS == null MINUS == null

In constructor: MINUS
PLUS != null MINUS == null

In static initialiser
PLUS != null MINUS != null

In constructor: after static
PLUS != null MINUS != null
public class Operation {

    private final static Operation PLUS = new Operation("PLUS");
    private final static Operation MINUS = new Operation("MINUS");

    static {
        System.out.println("In static initialiser");
        System.out.print("PLUS = " + PLUS);
        System.out.println("tMINUS = " + MINUS);
    }

    public Operation(String s) {
        System.out.println("In constructor: " + s);
        System.out.print("PLUS = " + PLUS);
        System.out.println("tMINUS = " + MINUS);
    }

    public static void main(String[] args) {
        Operation afterStatic = new Operation ("after static");
    }    
}

Operation常量是静态块中按照出现顺序创建的静态字段。

static { 
    // instantiate enum instances here
    ...
    // Initialize map from constant name to enum constant     
    for (Operation op : values())       
       stringToEnum.put(op.toString(), op);   
} 

The static blocks execute in order of appearance (you can have multiple static blocks), when the class loader loads the class, eg. it runs before the constructor.

链接地址: http://www.djcxy.com/p/6492.html

上一篇: 我如何从它的字符串值查找Java枚举?

下一篇: 将Enum类型wrt中的静态块的执行顺序传递给构造函数