为什么Enums中的静态和实例init块的行为与Classes中的不同

pan*_*ter 5 java enums scjp initialization open-closed-principle

在学习Java认证测试时,我了解到静态初始化块在加载类时按照源代码中的外观顺序运行一次,每次创建实例时运行实例初始化块,并且构造函数中的代码每次运行之后创建一个实例.为了测试我创建了一个带有一些静态和实例初始化块的类以及一个带有打印内容的构造函数.一切都按预期工作 - 除了我认为"加载"意味着只是在运行时,但我想它发生在第一个实例创建时,因为我根本没有得到任何输出,除非我创建至少1个类的实例.然后我用enum尝试了同样的命令并且命令全部关闭.首先,初始化块对枚举在代码中首次引用时枚举所具有的每个值运行一次,其次是在我假设为实例初始化块之后标记为静态的init块!这与我的预期相反.这是我的问题的细分.

  1. 为什么标记为static的init块在枚举中最后运行?
  2. 枚举可以有实例init块吗?
  3. 为什么我认为的块是实例初始化块只在加载枚举时运行一次,而不是每次引用新的枚举值时?
  4. 类"静态"初始化块在"加载"类时运行.加载是什么意思?当一个对象在类中实例化时,它只出现一次吗?

谢谢!这对我来说非常困惑.

public class EnumInit {
public static void main(String[] args) {
    System.out.println(Color.RED.toString() + " Main");
    MyInit myInit = new MyInit();
    System.out.println(Color.BLUE.toString() + " Main");
    MyInit mySecondInit = new MyInit();

}
}

enum Color {    
RED, BLUE, GREEN;
String instanceVar = "Enum Instance Variable Text";
static { System.out.println("Enum Static init block 1"); }
{ System.out.println("Enum Instance init block 1"); }
static { System.out.println("Enum Static static init block 2"); }
Color() { 
    System.out.println(instanceVar);
    System.out.println("Enum String Literal"); 
}
{ System.out.println("Enum Instance init block 2"); }   
}

class MyInit {
String instanceVar = "Class Instance Variable Text";
static { System.out.println("Class Static init block 1"); }
{ System.out.println("Class Instance init block 1"); }
static { System.out.println("Class Static static init block 2"); }
MyInit() { 
    System.out.println(instanceVar);
    System.out.println("Class String Literal"); 
}
{ System.out.println("Class Instance init block 2"); }  
}
Run Code Online (Sandbox Code Playgroud)

Sot*_*lis 8

Java语言规范是怎么enum常数

除了枚举类型E从Enum继承的成员之外, 对于每个声明的名称为n的枚举常量,枚举类型都有一个隐式声明的名为n的类型为E的公共静态最终字段.这些字段被认为是在在枚举类型中显式声明的任何静态字段之前,与相应的枚举常量相同的顺序.每个这样的字段被初始化为与其对应的枚举常量.

所以

enum Color {    
    RED, BLUE, GREEN;
    ...
}
Run Code Online (Sandbox Code Playgroud)

实际上是

public static final Color RED = new Color();
public static final Color BLUE = new Color();
public static final Color GREEN = new Color();
Run Code Online (Sandbox Code Playgroud)

这将在static你拥有的块之前得到评估.

为什么标记为static的init块在枚举中最后运行?

往上看.

枚举可以有实例init块吗?

是的,编译你的代码,你会看到.

为什么我认为的块是实例初始化块只在加载枚举时运行一次,而不是每次引用新的枚举值时?

枚举常量初始化后,将创建(实例化)枚举常量.您不会在enum任何时候创建新的

Color color = Color.RED;
Run Code Online (Sandbox Code Playgroud)

您只是引用已创建的现有对象.

类"静态"初始化块在"加载"类时运行.加载是什么意思?当一个对象在类中实例化时,它只出现一次吗?

当第一次在JVM中引用类时,它由ClassLoader和初始化加载.在这里阅读更多相关信息.