java输入枚举型_Java 枚举型为什么是静态的,以及是怎么实现的?

确实,枚举类型总让我们觉着怪怪的,无论是语法还是静态非静态,还是操作方法,总让人觉着它和数组、列表等格格不入。那到底是为什么呢?

我们从本质分析下java的枚举类型。

1 枚举类型初探

枚举类型,其语法总让人觉着怪怪的,如下:

简单的一行,就定义了包含四个值的枚举类型,缺总让人觉着语法有点怪异。而在使用时:

就可以得到输出:

那我们简单的一行定义中,到底发生了什么?枚举类型在编译时是怎样实现的?它还有着怎样的特点?

我们将会分几节对Java中的枚举类型进行介绍。

2 枚举产生之前

如果不使用枚举,我们要对“春夏秋冬”这四个值分别赋予一个数字,则常见的操作为:

上述方法定义十分繁琐,而且容易出错。例如我们定义的int数字出现重复,编译器也不会给出任何的警示。同时,这样的操作是实在太频繁了,最终Java 5中增加了枚举类型。

而是用枚举类型后,一切就变成了如下所示的简单几行:

而且,Java自动给按照枚举值出现的顺序,从0开始分配了编号。通过name()可以获得枚举值的名称,通过ordinal()可以获得枚举值的编号。

3 枚举实现原理

那我们定义枚举类型后,到底发生了什么呢?我们对枚举的实现原理进行探究。

首先,我们在实现Season枚举类时,并没有定义name()和ordinal()方法。我们从这里入手,点击该方法后,发现进入了一个抽象类:

并且,我们发现编译器不允许我们自行实现该抽象类从而构造一个新的类。但是,既然我们的Season枚举类可以调用其中的方法,因此Season枚举类应该是继承了该抽象类。

为了验证这一猜想,我们让Season类继承一个其他的类,发现果然不可以,因为Java是不允许多继承的。

具体,我们对Season类进行反编译,即:java -p Season.class,得到反编译后的结果:

我们看到,对与枚举类,有很多值的注意的点:

枚举类在经过编译后确实是生成了一个扩展了java.lang.Enum的类

枚举类是final的,因此我们无法再继承它了

我们定义的每个枚举值都是该类中的一个成员,且成员的类型仍然是Season类型

枚举类中被默认增加了许多静态方法,例如values()等

为了进一步了解每个方法中的操作,我们使用java -p -c Season.class每个方法中的字节码:

根据字节码,我们还原其操作代码,大致如下:

注意:以下代码为笔者自己翻译,如果有好的字节码查看工具请一定要留言告诉我啊。

通过这里我们可以看到,在类的static操作中,编译器帮助我们生成每个枚举值的对象。

4 总结

我们在总结一下,我们使用enum定义的枚举类型,会在编译之后转化为一个继承了java.lang.Enum的类,而我们定义的每个枚举值都会在类的初始化阶段被实例化为我们所定义的枚举类的一个对象。

同时,编译器还帮我们在类中增加了两个方法,分别是:values()和valueOf()。

至此,我们对Java的枚举对象有了彻底的认识。

但是,我们依旧有着很多的疑惑:

编译器插入的方法和正常的方法有无不同

枚举类型还有哪些使用上的注意点,例如相关方法和操作

枚举类型的实现上还有哪些特殊之处

这些,我们在接下来的文章中继续分析。

—END—

微信公众号:程序员进阶架构师

分享让你从程序员进阶架构师的原创干货!

欢迎关注我们,不错过每期的原创干货!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值