我正在开发一个LALG编译器到我的大学课程
Java 1.6.所以我做了一个类型类和语法类.
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; } }
当我调用EnumTypes.E.getEnumTiposValue().getValues()其中应该是EnumTypes.F值为NULL.
主要
public class Main { public static void main(String[] args) { //prints [A,B,null,D] System.out.println(Arrays.toString(EnumTypes.E.getEnumTiposValue().getValues())); } }
有一个解决方法或类似的东西?
谢谢!
解决方法
从本质上说,在完全构造类之前,即在构造函数完成之前,允许对对象的引用在类之外是非常危险的.枚举是单身人士.这里你有两个类,其构造函数以循环依赖关系接收彼此的实例.加载到这个类加载是懒惰的,所以类将被加载和枚举实例创建,当你走,这听起来很合理的结果结果取决于枚举初始化的顺序.
我现在不能引用JLS的对应点(我会寻找它),但我相信如果你允许引用一个对象来从构造函数外部“离开类”(这里由于枚举是由JVM初始化的单例),JVM可以自由地做一些奇怪的事情.
编辑:这些来自JLS的点对于这种情况是重要的:
> 17.5.2 – 构造该对象的线程内的对象的最终字段的读取是按照通常的事先规则在构造函数内对该字段的初始化进行排序的.如果在构造函数中设置了字段之后发生读取,则会看到分配最终字段的值,否则会看到默认值.由于枚举值被内部处理为静态最终字段(参见下面的16.5),如果从构造函数引用第一个枚举的另一个枚举的构造函数内部引用一个枚举,则这两个对象中的至少一个尚未被完全初始化,所以在这一点上引用可能仍然为null.
> 16.5 – 枚举常数的类体内任何构造的明确赋值/取消分配状态由类的常规规则
> 8.3.2 – 字段初始化规则
> 12.4.1 – 初始化时发生