Enum类型中静态块的执行顺序w.r.t到构造函数

时间:2012-08-02 11:43:13

标签: java enums jls

这来自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);
  }
  

请注意,Operation常量被放入stringToEnum映射中   来自在创建常量后运行的静态块。   试图使每个常量从它自己的地方放入地图   构造函数会导致编译错误。这是件好事,   因为如果它是合法的,它会导致NullPointerException。枚举   构造函数不允许访问枚举的静态字段,   除了编译时常量字段。这种限制是必要的   因为这些静态字段尚未初始化   施工人员。

我的问题是关于这一行:

  

“请注意,Operation常量被放入stringToEnum映射中   来自在创建常量后运行的静态块“。

我认为静态块在构造函数运行之前执行。实际上是在类加载时执行的。

我在这里缺少什么?

3 个答案:

答案 0 :(得分:13)

我理解你的问题是:为什么要保证在运行静态块之前初始化枚举常量。答案在JLS中给出,并在#8.9.2.1中给出了一个具体示例,其中包含以下说明:

  

静态初始化从上到下发生。

和枚举常量隐式最终为静态,并在静态初始化程序块之前声明。

修改

行为与普通班级没有什么不同。下面的代码打印:

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");
    }    
}

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

当类加载器加载类时,static块按出现顺序执行(可以有多个静态块),例如。它在构造函数之前运行。