简体   繁体   English

为什么Java枚举常量初始化不完整?

[英]Why the Java enum constants initialization is not complete?

I stumbled upon a very weird bug and I can't explain why it happens. 我偶然发现了一个非常奇怪的错误,我无法解释它为什么会发生。 Imagine the following enum: 想象一下以下枚举:

import java.awt.Color;

public class test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        System.out.println(MyEnum.CONSTANT1.get());
        System.out.println(MyEnum.CONSTANT2.get());
    }

    private enum MyEnum {
        CONSTANT1(staticMethod1()),
        CONSTANT2(staticMethod2());

        private static final Color WHY_AM_I_NULL = new Color(255, 255, 255);

        private final Color color;

        private MyEnum(Color color) {
            this.color = color;
        }

        public Color get() {
            return color;
        }

        private static Color staticMethod1() {
            return new Color(100, 100, 100);
        }

        private static Color staticMethod2() {
            return WHY_AM_I_NULL;
        }
    }

}

The results when you run this are: 运行它时的结果是:

java.awt.Color[r=100,g=100,b=100]
null

The question is, why the second one is null? 问题是,为什么第二个是空的?

Ammendment: If you put the WHY_AM_I_NULL in a private static class inside the enum, then it is initialized first. 修改:如果你把WHY_AM_I_NULL放在枚举中的私有静态类中,那么它首先被初始化。

The problem is that all static fields (and enum instances count as such) are initialized in their declared order ( specification ). 问题是所有静态字段(以及枚举实例都这样计算)都按其声明的顺序( 规范 )进行初始化。 So when CONSTANT2 is instantiated, the field WHY_AM_I_NULL is still not initialized (and therefore null ). 因此,当实例化CONSTANT2时,字段WHY_AM_I_NULL仍未初始化(因此为null )。

As you can't put the field before the enum instances, you have to find some other way of doing what you want (eg, putting the field outside the enum class). 由于您无法将字段放在枚举实例之前,因此您必须找到其他方法来执行您想要的操作(例如,将字段放在枚举类之外)。 If you tell us, what you really want to accomplish, one could make further suggestions. 如果你告诉我们,你真正想要实现的目标,可以提出进一步的建议。

Edit: If you put WHY_AM_I_NULL in a nested class, the fields of this class will be initialized as soon as the class is first accessed (ie, in this case during the execution of staticMethod2 ). 编辑:如果将WHY_AM_I_NULL放在嵌套类中,则只要首次访问类(即,在执行staticMethod2期间),就会初始化此类的字段。

Enums are the compiler feature. 枚举是编译器功能。 Actually compiler creates class named MyEnum that contains 2 public static fields CONSTANT1 and CONSTANT2 and other code. 实际上编译器创建了名为MyEnum的类,它包含2个公共静态字段CONSTANT1和CONSTANT2以及其他代码。

Static initialization is done up-to-down, so the CONSTANT2 is created and is initialized before static variable WHY_AM_I_NULL. 静态初始化是从上到下完成的,因此创建CONSTANT2并在静态变量WHY_AM_I_NULL之前初始化。 This is why WHY_AM_I_NULL is null when CONSTANT2 is being initialized. 这就是为什么在初始化CONSTANT2时WHY_AM_I_NULL为空的原因。

WHY_AM_I_NULL is null when staticMethod2 is invoked - this is how JLS specifies initialization WHY_AM_I_NULL为null,则调用staticMethod2时-这是怎么JLS指定初始化

In a different sequence you'd get 100, 255 instead of 100, null : 在不同的序列中,您将获得100, 255而不是100, null

private static final Color WHY_AM_I_NULL = new Color(255, 255, 255);
private enum MyEnum {
    CONSTANT1(staticMethod1()),
    CONSTANT2(staticMethod2());
    //...

This is because the static fields (including enum values) are initialized in the order they appear in the file. 这是因为静态字段(包括枚举值)按它们在文件中出现的顺序初始化。

So CONSTANT1 , and CONSTANT2 get initialized before WHY_AM_I_NULL , therefore CONSTANT2 is initialized with null . 因此CONSTANT1CONSTANT2WHY_AM_I_NULL之前初始化,因此CONSTANT2初始化为null

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM