Java枚举属性根据访问顺序返回null
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java枚举属性根据访问顺序返回null,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3240字,纯文字阅读大概需要5分钟。
内容图文
我正在用Java探索枚举,看看它们如何被滥用,并且遇到了无法解释的行为.考虑以下类别:
public class PROGRAM {
public enum ENUM {;
public enum ANIMALS {;
public enum CATS {
FELIX(DOGS.AKAME),
GARFIELD(DOGS.WEED),
BUBSY(DOGS.GIN);
CATS(DOGS dog) {this.RIVAL = dog;}
public DOGS RIVAL;
}
public enum DOGS {
GIN(CATS.FELIX), WEED(CATS.BUBSY), AKAME(CATS.GARFIELD);
DOGS(CATS cat) {this.RIVAL = cat;}
public CATS RIVAL;
}
}
}
public static void main(String[] args) {
System.out.println(ENUM.ANIMALS.CATS.GARFIELD.RIVAL);
System.out.println(ENUM.ANIMALS.DOGS.GIN.RIVAL);
}
}
如预期的那样,主函数中的第一条语句将显示“ WEED”.第二个将打印“ null”.但是,如果您将其切换,即
System.out.println(ENUM.ANIMALS.DOGS.GIN.RIVAL);
System.out.println(ENUM.ANIMALS.CATS.GARFIELD.RIVAL);
第一条语句将显示“ FELIX”,第二条语句将显示“ null”.有没有人可以解释这种现象?
作为参考,我正在运行Java(TM)SE运行时环境(内部版本1.8.0_05-b13)
解决方法:
这与枚举和类初始化有关.
首先,枚举只是一个带有常量字段的奇特类. That is, the enum constants you declare are in reality just static fields.所以
enum SomeEnum {
CONSTANT;
}
编译成类似于
final class SomeEnum extends Enum<SomeEnum> {
public static final SomeEnum CONSTANT = new SomeEnum();
}
其次,static fields are initialized in the left to right order they appear in the source code.
Next, execute either the class variable initializers and static
initializers of the class, or the field initializers of the interface,
in textual order, as though they were a single block.
在下面的
final class SomeEnum extends Enum<SomeEnum> {
public static final SomeEnum CONSTANT = new SomeEnum();
public static final SomeEnum CONSTANT_2 = new SomeEnum();
}
首先将初始化CONSTANT,然后第二次初始化CONSTANT_2.
第四,如果当前线程正在初始化一个类,则可以正常进行.
If the
Class
object forC
indicates that initialization is in progress
forC
by the current thread, then this must be a recursive request for
initialization. ReleaseLC
and complete normally.
这一切如何融合在一起?
这个
ENUM.ANIMALS.CATS.GARFIELD.RIVAL
被评估为
CATS cat = ENUM.ANIMALS.CATS.GARFIELD;
DOGS rvial = cat.RIVAL;
首次访问GARFIELD会强制初始化枚举类型CATS.这开始初始化CATS中的枚举常量.编译后,看起来像
private static final CATS FELIX = new CATS(DOGS.AKAME);
private static final CATS GARFIELD = new CATS(DOGS.WEED);
private static final CATS BUBSY = new CATS(DOGS.GIN);
这些按顺序初始化.因此FELIX排名第一.作为其新实例创建表达式的一部分,它访问DOGS.AKAME,但DOGS类型尚未初始化,因此Java开始对其进行初始化.编译后的DOGS枚举类型看起来像
private static final DOGS GIN = new DOGS(CATS.FELIX);
private static final DOGS WEED = new DOGS(CATS.BUBSY);
private static final DOGS AKAME = new DOGS(CATS.GARFIELD);
因此,我们从GIN开始.在其新的实例创建表达式中,它尝试访问CATS.FELIX. CATS当前正在初始化,因此我们继续. CATS.FELIX尚未分配值.目前,它在堆栈中的位置较低.因此其值为空.因此,GIN.RIVALS获得对null的引用.所有DOGS的RIVAL都发生相同的情况.
当所有DOGS都初始化后,执行返回到
private static final CATS FELIX = new CATS(DOGS.AKAME);
其中DOGS.AKAME现在引用完全初始化的DOGS对象.这将分配给它的CATS#RIVAL字段.每个CATS都相同.换句话说,为所有CATS的RIVAL字段分配了DOGS参考,但没有相反的方式.
对语句重新排序只需确定首先枚举哪种枚举类型.
内容总结
以上是互联网集市为您收集整理的Java枚举属性根据访问顺序返回null全部内容,希望文章能够帮你解决Java枚举属性根据访问顺序返回null所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。