Java枚举构造方法中静态字段为null的原因与初始化顺序疑问
Java枚举初始化的奇怪现象与解析
先看这段枚举代码:
import java.io.File; public enum Test { TEST ; private static final File TEST_FILE = new File("test"); Test() { test(); } private void test() { System.out.println(TEST_FILE); } }
运行后会发现,TEST_FILE输出的是null,而非预期的test文件对象。而如果把输出逻辑放到静态代码块中,就能得到正确的TEST_FILE实例:
static { System.out.println(TEST_FILE); }
问题1:为什么会出现这种情况?
这本质是Java类初始化顺序导致的。枚举类属于特殊的类,它的枚举常量是类的静态成员。JVM初始化类时,会严格按照代码中静态成员的定义顺序执行:
- 枚举常量
TEST在TEST_FILE之前定义,JVM会先尝试创建TEST实例 - 创建实例时调用枚举构造方法,构造方法又调用
test()方法,此时TEST_FILE还没被初始化(因为它在TEST之后定义),所以输出null - 等所有枚举实例创建完成后,才会初始化后续的静态字段
TEST_FILE
问题2:枚举构造方法的初始化顺序是怎样的?
枚举类的初始化流程可以拆解为以下步骤:
- 当枚举类第一次被加载或访问时,JVM触发类的初始化过程
- 按代码中枚举常量的定义顺序,依次创建每个枚举实例:每个实例创建时,会调用枚举的构造方法,执行构造方法内的逻辑
- 所有枚举实例都创建完成后,才会按顺序初始化类中剩余的静态字段(即枚举常量之后定义的静态成员)
- 最后执行类中的静态代码块(静态代码块的执行顺序和它在代码中的位置有关,位于静态字段之后的话,会在对应字段初始化后执行)
内容的提问来源于stack exchange,提问作者micartey
相关产品推荐
相关产品推荐

