Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 枚举类型w.r.t中静态块到构造函数的执行顺序_Java_Enums_Jls - Fatal编程技术网

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

Java 枚举类型w.r.t中静态块到构造函数的执行顺序,java,enums,jls,Java,Enums,Jls,这来自有效的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

这来自有效的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);
  }
//在枚举类型上实现fromString方法
私有静态最终映射stringToEnum
=新HashMap();
静态{//初始化从常量名到枚举常量的映射
对于(操作op:values())
stringToEnum.put(op.toString(),op);
}
//返回字符串的操作,如果字符串无效,则返回null
来自字符串(字符串符号)的公共静态操作{
返回stringToEnum.get(符号);
}
请注意,操作常量被放入stringToEnum映射中 从创建常量后运行的静态块。 试图使每个常量从它自己的常量进入映射 构造函数将导致编译错误。这是一件好事, 因为如果它是合法的,它会导致NullPointerException。枚举 构造函数不允许访问枚举的静态字段, 编译时常量字段除外。这一限制是必要的 因为当 构造函数运行

我的问题是关于线路:

请注意,操作常量被放入stringToEnum映射中 从创建常量后运行的静态块”

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


这里缺少什么?

操作
常量是按显示顺序在静态块中创建的静态字段

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

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

我理解您的问题是:为什么保证在运行静态块之前初始化枚举常量。中给出了答案,中给出了具体示例,并进行了以下说明:

静态初始化从上到下进行

枚举常量是隐式的final static,在静态初始值设定项块之前声明

编辑

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

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

请参见,假设该操作表示计算器的操作。常量(加、减、除、乘)将仅在构造函数运行后创建。因此,我对如何在构造函数运行之前初始化常量感到困惑。保存常量的隐式静态最终字段可以在构造函数运行之前创建,但只能在构造函数运行之后分配。每个常量(加、减…)将在各自的构造函数运行之后初始化。如果需要,执行顺序将是:
PLUS=newoperation(…);减号=新操作(…);静态块
这就是为什么Bloch说,如果您试图从构造函数填充映射,因为在所有构造函数都运行完之前,常量还没有初始化。因此,构造函数实际上在静态块之前运行。这意味着枚举行为与其他普通类是分开的。是吗?不是-我在我的答案中添加了一个普通类的例子。枚举以类似的方式运行,只是其中一些是隐式的。
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");
    }    
}