枚举枚举为NULL [英] Enum of Enum is NULL

查看:214
本文介绍了枚举枚举为NULL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为我的大学课程Java 1.6开发LALG编译器。所以我做了一个类型类和语法类。



枚举类型

  public enum EnumTypes {

A(OLA),
B(MUNDO),
C(HELLO),
D(WORLD),

/ **
*下面的顺序是有意义的。
*还原它,你会得到一个NULL列表的类型。
* /

I(EnumGrammar.THREE),
H(EnumGrammar.TWO),
F(EnumGrammar.ONE),
E(EnumGrammar 。零);

private String strValue;
private EnumGrammar enumGrammarValue;

private EnumTypes(String strValue){
this.strValue = strValue;
}

private EnumTypes(EnumGrammar enumGrammarValue){
this.enumGrammarValue = enumGrammarValue;
}

public String getStrValue(){
return strValue;
}

public EnumGrammar getEnumTiposValue(){
return enumGrammarValue;
}
}

EnumGrammar

  public enum EnumGrammar {

ZERO(EnumTypes.A,EnumTypes.B,EnumTypes.F,EnumTypes.D ),
ONE(EnumTypes.C),
TWO(EnumTypes.B,EnumTypes.H),
THREE(EnumTypes.D,EnumTypes.A,EnumTypes.C);

private EnumTypes [] values;

private EnumGrammar(EnumTypes ... values){
this.values = values;
}

public EnumTypes [] getValues(){
返回值;
}
}

当我调用 EnumTypes。 E.getEnumTiposValue()。getValues()其中应该是 EnumTypes.F 值是 NULL 。 / p>

主要

  

public static void main(String [] args){
//打印[A,B,null,D]
System.out.println(Arrays.toString(EnumTypes 。.E.getEnumTiposValue()的GetValues()));
}

}

有一个解决方法或类似的东西



谢谢!

解决方案

本质上,在构建完毕之前,允许在对类进行完全构造之前,允许引用对象来引用该类的非常危险的事情。枚举是单身人士。在这里,您有两个类,其构造函数以循环依赖关系接收彼此的实例。加载到这个类加载是懒惰的,所以类将被加载和枚举实例创建,当你走,这听起来很合理的结果结果取决于枚举初始化的顺序。



我现在不能引用JLS的对应点(我会寻找它),但我相信如果你允许引用一个对象来离开类构造函数(由于枚举是由JVM初始化的单例),JVM可以自由地做一些奇怪的事情。



编辑:这些来自JLS的点对于这种情况非常重要:




  • 17.5.2 - 读取对象的最后一个字段构造该对象的线程相对于构造函数中的该字段的初始化按照通常的事先规则排序。如果在构造函数中设置了字段之后发生读取,则会看到分配最终字段的值,否则会看到默认值。由于枚举值在内部被处理为静态final字段(见16.5下面),如果您引用另一个枚举的构造函数内部的一个枚举,该枚举的构造函数引用了第一个枚举,则这两个对象中的至少一个尚未被完全初始化,因此此时引用可能仍为null。 li>
  • 16.5 - 枚举常数的类体内的任何构造的确定赋值/取消分配状态由类的通常规则

  • 8.3。 2 - 字段初始化规则

  • 12.4.1 - 初始化时


I'm developing a LALG compiler to my college course on Java 1.6. So I did a types class and grammar class.

EnumTypes

public enum EnumTypes {

    A("OLA"),
    B("MUNDO"),
    C("HELLO"),
    D("WORLD"),

    /**
     * The order below is reversed on purpose.
     * Revert it and will you get a NULL list of types furder.
     */

    I(EnumGrammar.THREE),
    H(EnumGrammar.TWO),
    F(EnumGrammar.ONE),
    E(EnumGrammar.ZERO);

    private String strValue;
    private EnumGrammar enumGrammarValue;

    private EnumTypes(String strValue) {
        this.strValue = strValue;
    }

    private EnumTypes(EnumGrammar enumGrammarValue) {
        this.enumGrammarValue = enumGrammarValue;
    }

    public String getStrValue() {
        return strValue;
    }

    public EnumGrammar getEnumTiposValue() {
        return enumGrammarValue;
    }
}

EnumGrammar

public enum EnumGrammar {

    ZERO(EnumTypes.A,EnumTypes.B,EnumTypes.F,EnumTypes.D),
    ONE(EnumTypes.C),
    TWO(EnumTypes.B,EnumTypes.H),
    THREE(EnumTypes.D,EnumTypes.A,EnumTypes.C);

    private EnumTypes[] values;

    private EnumGrammar(EnumTypes ... values) {
        this.values = values;
    }

    public EnumTypes[] getValues() {
        return values;
    }
}

When I call EnumTypes.E.getEnumTiposValue().getValues() where are supposed to be the EnumTypes.F value is NULL.

Main

public class Main {

    public static void main(String[] args) {
        //prints [A, B, null, D]
        System.out.println(Arrays.toString(EnumTypes.E.getEnumTiposValue().getValues()));
    }

}

There are a workaround or something like that?

Thanks!

解决方案

Essentially, it is always a very risky thing to allow a reference to an object to get outside of the class before the class is fully constructed, that is before the constructor is finished. Enums are singletons. Here you have two classes whose constructors receive each other's instances in a circular dependency. Add to this that class loading is lazy, so the classes will be loaded and enum instances created as you go and it sounds quite reasonable that the ends result depends on the order in which the enums are initialized.

I can't quote the corresponding point from JLS right now (I'll look for it), but I believe that if you allow a reference to an object to "leave the class" from outside of the constructor (which happens here due to enums being singletons initialized by the JVM), the JVM is free to do something strange.

EDIT: these points from the JLS are of importance for the case:

  • 17.5.2 - A read of a final field of an object within the thread that constructs that object is ordered with respect to the initialization of that field within the constructor by the usual happens-before rules. If the read occurs after the field is set in the constructor, it sees the value the final field is assigned, otherwise it sees the default value. Since enum values are internally treated like static final fields (see 16.5 below), if you reference one enum from inside the constructor of another enum whose constructor references the first one, at least one of these two objects will not yet have been fully initialized and so the reference may still be null at this point.
  • 16.5 - The definite assignment/unassignment status of any construct within the class body of an enum constant is governed by the usual rules for classes
  • 8.3.2 - rules for initialization of fields
  • 12.4.1 - when initialization occurs

这篇关于枚举枚举为NULL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆