Java-Enum枚举类

介绍 enum 的全称为 enumeration, 是 JDK 1.5 中引入的新特性,存放在 java.la…

介绍
enum 的全称为 enumeration, 是 JDK 1.5 中引入的新特性,存放在 java.lang 包中。
使用关键字enum来定义枚举类,枚举类是一个特殊的类,大部分功能和普通类是一样的。
区别为:枚举类继承了java.lang.Enum类,而不是默认的Object类。
而java.lang.Enum类实现了java.lang.Serializable和java.lang.Comparable接口。
非抽象的枚举类默认会使用final修饰,因此不能派生子类

枚举类型使用的最常用类型就是枚举常量,下面通过一个简单的Demo来说明枚举的原理。
使用示例:

从简单的示例,不能看出枚举的特点和枚举的具体实现。
下面我们通过 jad工具来反编译Color类, 通过jad -sjava Color.class反编译出一份java文件:

从反编译的类中,可以看出, 我们使用enum关键字编写的类,在编译阶段编译器会自动帮我们生成一份真正在jvm中运行的代码。
Color 类继承自 Enum类:

Enum类接受一个继承自Enum的泛型.(在反编译java文件中没有体现泛型是因为,泛型在编译阶段就会被类型类型擦除(参考泛型详解,链接:泛型详解),替换为具体的实现)。
从反编译的Color类中可以看出,在enum关键字的类中,第一行 (准确的说是第一个分号前) 定义的变量,都会生成一个 Color实例,且它是在静态域中进行初始化的, 而静态域在类加载阶段的cinit中进行初始化,所以枚举对象是线程安全的,由JVM来保证.
生成的枚举类有 Color $VALUES[];成员变量,外部可以通过values()方法获取当前枚举类的所有实例对象。

通过上述查看编译后的枚举类后,我们可以清晰看到枚举类编译后的类内容信息,但是笔者仍旧抱有怀疑的态度,于是就用反射做了验证。

源码:

运行结果:

可以得知,编译过后的Color类,含三个常量,两个方法,没有可见的构造方法。

先说一个案例,你需要让每一个星期几对应到一个整数,比如星期天对应0。由于枚举类在定义的时候会自动为每个变量添加一个顺序,从0开始。
假如你希望0代表星期天,1代表周一,并且你在定义枚举类的时候,顺序也是这个顺序,那你可以不用定义新的变量,就像这样:

这个时候,星期天对应的ordinal值就是0,周一对应的就是1,满足你的要求。但是,如果你这么写,那就有问题了:

我把SUN放到了最后,但是我还是希0代表SUN,1代表MON怎么办呢?默认的ordinal是指望不上了,因为它只会傻傻的给第一个变量0,给第二个1、、、
所以,我们需要自己定义变量!
看代码:

我们对上面的代码做了一些改变:
首先,我们在每个枚举变量的后面加上了一个括号,里面是我们希望它代表的数字。
然后,我们定义了一个int变量,然后通过构造函数初始化这个变量。
你应该也清楚了,括号里的数字,其实就是我们定义的那个int变量。这句叫做自定义变量。

请注意:这里有三点需要注意:
一定要把枚举变量的定义放在第一行,并且以分号结尾。
构造函数必须私有化。事实上,private是多余的,你完全没有必要写,因为它默认并强制是private,如果你要写,也只能写private,写public是不能通过编译的。
自定义变量与默认的ordinal属性并不冲突,ordinal还是按照它的规则给每个枚举变量按顺序赋值。

好了,你已经掌握了上面的知识,你想,既然能自定义一个变量,能不能自定义两个呢?
当然可以:

每一个枚举类型极其定义的枚举变量在JVM中都是唯一的
这句话的意思是枚举类型它拥有的实例在编写的时候,就已经确定下,不能通过其他手段进行创建,且枚举变量在jvm有且只有一个对应的实例.

本文来自网络,不代表软粉网立场,转载请注明出处:https://www.rfff.net/p/8528.html

作者: HUI

发表评论

您的电子邮箱地址不会被公开。

返回顶部