枚举是一个非常古老的语言特性,用来实现具名的有限集合,在 C/C++ 中使用广泛。而 Java 在 Java SE5 才引入枚举。也许语言设计者觉得既然是后引入该特性,那么一定要在这个特性上支持比其他语言更多的特性。这些特性的确让 Java 的枚举功能看起来更加“成熟”,同时也引入了一些复杂性,需要开发者关注。
枚举是一个不能继承的常规类
定义一个一周七天的枚举类型:
╰─➤ javap EnumWeekDay
Compiled from "EnumWeekDay.java"
public final class EnumWeekDay extends java.lang.Enum<enumweekday> {
public static final EnumWeekDay Mon;
public static final EnumWeekDay Tue;
public static final EnumWeekDay Wed;
public static final EnumWeekDay Thu;
public static final EnumWeekDay Fri;
public static final EnumWeekDay Sat;
public static final EnumWeekDay Sun;
public static EnumWeekDay[] values();
public static EnumWeekDay valueOf(java.lang.String);
static {};
}</enumweekday>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
╰─➤
javap
EnumWeekDay
Compiled
from
"EnumWeekDay.java"
public
final
class
EnumWeekDay
extends
java
.
lang
.
Enum
&
lt
;
enumweekday
&
gt
;
{
public
static
final
EnumWeekDay
Mon
;
public
static
final
EnumWeekDay
Tue
;
public
static
final
EnumWeekDay
Wed
;
public
static
final
EnumWeekDay
Thu
;
public
static
final
EnumWeekDay
Fri
;
public
static
final
EnumWeekDay
Sat
;
public
static
final
EnumWeekDay
Sun
;
public
static
EnumWeekDay
[
]
values
(
)
;
public
static
EnumWeekDay
valueOf
(
java
.
lang
.
String
)
;
static
{
}
;
}
&
lt
;
/
enumweekday
&
gt
;
枚举类型的关键字
enum
其实只是一个语法糖,编译器最终把它转化为一个final类,因此枚举是不可继承的。
枚举类型都继承自
java.lang.Enum
类。
枚举的每一个取值被编译器传化为了一个个
static final
属性。
本质上,这就是一个普通类,因此你可以在枚举是添加各种方法,甚至是main方法。
神奇的
values()
方法
从上面我们可以看出枚举类型被添加了一个静态的
values()
方法,但是 java.lang.Enum 并没有该方法。其实,这个方法是编译器添加的。通过这个方法可以获取到该枚举类型的所有取值。这个方法在需要遍历枚举取值,进行判断筛选的场景非常有用,可参考下例的
getByZhName
方法。
在枚举中保存其他信息
在 C 中,枚举可以简单的理解为具名的整型子集。Java 扩展了这个属性,使得可以在枚举中保存其他信息。
定义一个水果枚举类,并包含中文信息:
EnumFruit(String zhName) {
System.out.println("enum init:" + zhName);
this.zhName = zhName;
* Getter method for property <tt>zhName</tt>.
* @return property value of zhName
public String getZhName() {
return zhName;
public EnumFruit getByZhName(String zhName) {
for (EnumFruit fruit : values()) {
if (fruit.getZhName().equals(zhName)) {
return fruit;
return null;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public
enum
EnumFruit
{
APPLE
(
"苹果"
)
,
BANANA
(
"香蕉"
)
,
ORANGE
(
"橘子"
)
;
private
String
zhName
;
EnumFruit
(
String
zhName
)
{
System
.
out
.
println
(
"enum init:"
+
zhName
)
;
this
.
zhName
=
zhName
;
}
/**
* Getter method for property <tt>zhName</tt>.
*
* @return property value of zhName
*/
public
String
getZhName
(
)
{
return
zhName
;
}
public
EnumFruit
getByZhName
(
String
zhName
)
{
for
(
EnumFruit
fruit
:
values
(
)
)
{
if
(
fruit
.
getZhName
(
)
.
equals
(
zhName
)
)
{
return
fruit
;
}
}
return
null
;
}
}
public class EnumUser {
public static void main(String[] args) {
EnumFruit fruit = EnumFruit.APPLE;
System.out.println(fruit);
使用 EnumSet 和 EnumMap 提供性能
如果要在把枚举使用在 Set、Map 等集合场景,请使用
EnumSet
和
EnumMap
。 EnumSet 使用了 bit vector 来标记元素,EnumMap 内部将 Map 实现简化为了数组,因此可以获得更好的性能。
Java 的枚举语言特性作为一个后来者,的确带来了更加“成熟”和“丰富”的实现。但是,这些丰富的特性是否一定要在日常的项目中使用,我个人是不推荐的。就我个人理解,枚举最大的优点是类型和有限集合的约束,从而增强代码的一致性。因此,我提倡在项目代码中用 C 的枚举风格来使用 Java 枚举。此外,枚举并不是编程语言必须支持的特性,比如近段时间如日中天的 Golang 是不支持枚举的。既然是一个可有可无的语言特性,那就 use is as simple as possible 吧。
Java 语言中 Enum 类型的使用介绍
Java中的枚举与values()方法
–EOF–
此条目由
daniel
发表在
Design Pattern
、
Java
分类目录,并贴了
enum
、
java
、
枚举
标签。将
固定链接
加入收藏夹。