Java 中枚举中的静态(和最终)字段初始化

Static (and final) field initialization in an enum in Java

假设我有如下枚举类型的颜色:

public enum Colour
{
    RED, GREEN, BLUE;
}

我想按照那边的建议从这三种颜色中随机选择一种颜色:

但我不想一遍又一遍地打电话给values(),所以,我想出了如下办法:

public enum Colour
{
    RED, GREEN, BLUE;

    private static final Colour[] Values = values();

    public static Colour random()
    {
        return Values[(int) (Math.random() * Values.length)];
    }
}

问题是,它会一直有效吗?

这里让我感到困惑的是,当这个 private static final 字段的初始化发生时。它应该在完整的枚举列表完成后发生。我不认为它会很快发生,但我仍然想确定一下。

是的,此初始化将始终有效。枚举常量总是列在第一位,JLS, Section 8.9.3 保证它们将在任何其他正常 static 变量之前被初始化。

For each enum constant c declared in the body of the declaration of E, E has an implicitly declared public static final field of type E that has the same name as c. The field has a variable initializer consisting of c, and is annotated by the same annotations as c.

These fields are implicitly declared in the same order as the corresponding enum constants, before any static fields explicitly declared in the body of the declaration of E.

所有 static 字段都按顺序初始化,就好像它们是单个文本块一样,因此您的所有枚举常量都将在 Values 通过调用 values() 初始化之前初始化。

顺便说一下,static final 变量通常以所有大写字母命名,例如VALUES,按照标准 Java 命名约定。