Java 为什么枚举中的静态和实例init块的行为与类中的不同
在学习Java认证测试时,我了解到,静态初始化块在加载类时运行一次,按照在源代码中出现的顺序,实例初始化块在每次创建实例时运行,构造函数中的代码在每次创建实例之后运行。为了测试这一点,我创建了一个包含一些静态和实例init块的类,以及一个包含打印内容的构造函数。一切都按预期工作——除了我认为“loaded”只是指在运行时,但我猜它发生在创建第一个实例时,因为除非创建至少一个类实例,否则我根本不会得到任何输出。然后我用枚举尝试了同样的方法,结果顺序都被取消了。首先,在代码中首次引用枚举时,初始化块为枚举的每个值运行一次,其次——标记为static的init块在我假设的实例init块之后运行!这与我的预期相反。下面是我的问题的分类Java 为什么枚举中的静态和实例init块的行为与类中的不同,java,enums,initialization,scjp,open-closed-principle,Java,Enums,Initialization,Scjp,Open Closed Principle,在学习Java认证测试时,我了解到,静态初始化块在加载类时运行一次,按照在源代码中出现的顺序,实例初始化块在每次创建实例时运行,构造函数中的代码在每次创建实例之后运行。为了测试这一点,我创建了一个包含一些静态和实例init块的类,以及一个包含打印内容的构造函数。一切都按预期工作——除了我认为“loaded”只是指在运行时,但我猜它发生在创建第一个实例时,因为除非创建至少一个类实例,否则我根本不会得到任何输出。然后我用枚举尝试了同样的方法,结果顺序都被取消了。首先,在代码中首次引用枚举时,初始化块
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"); }
}
除了枚举类型E从枚举继承的成员之外,
对于每个名为n的已声明枚举常量,枚举类型都有一个
隐式声明的公共静态final字段名为n,类型为E
字段的声明顺序与
对应的枚举常量,显式位于任何静态字段之前
在枚举类型中声明。每个这样的字段都初始化为枚举
与之对应的常数
所以
实际上是
public static final Color RED = new Color();
public static final Color BLUE = new Color();
public static final Color GREEN = new Color();
它将在您拥有的静态
块之前得到评估
为什么标记为static的init块在枚举中最后运行
见上文
枚举是否可以具有实例初始化块
是的,编译您的代码,您将看到
为什么我认为是instance init块的块在加载枚举时只运行一次,而不是每次引用新的枚举值时都运行一次
初始化枚举类型后,将创建(实例化)枚举常量。您不会在任何时候创建新的enum
Color color = Color.RED;
您只是引用了一个已经创建的现有对象
类静态初始化块在类“加载”时运行。加载是什么意思?当一个对象在类中实例化时,它是否只发生一次
当类第一次在JVM中被引用时,它将由
类加载器加载并初始化 对于#4:类只有在得到有意义的使用后才会加载。这可能是在类上调用静态方法,或者创建实例,或者调用class.forName()或其他什么。我认为这是为了将当前加载到perma gen中的类的数量保持在最小值。因此,当每个隐式构造函数运行时,没有标记为静态的init块是否会运行,然后静态块最后运行?@paniclater是的,这些实例初始值设定项块是在new Color()时运行的代码>被隐式调用。由于enum
常量是您在enum
主体中声明的第一件事,因此这些常量总是发生在enum
中声明的任何静态
块之前。谢谢,这实际上使此过程非常清楚。@paniclater欢迎您。除非有什么不清楚的事情,你可以考虑接受答案。
Color color = Color.RED;