在 switch 语句中使用枚举类型想象起来好像很简单,但是看到很多人的写法都是有问题的。
所以下面通过一个例子谈一下正确的写法。

假设现在有如下枚举类的定义:

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/**
* 用户类型枚举类, 用于区分用户的身份.
*/
public enum UserType {
STUDENT(1), TEACHER(2), PARENT(3), SCHOOL_ADMIN(4), UNKNOWN(-1);
private int value;
UserType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public String getStringValue() {
return String.valueOf(value);
}
public static UserType valueOf(int value) {
UserType userType = null;
switch (value) {
case 1:
userType = STUDENT;
break;
case 2:
userType = TEACHER;
break;
case 3:
userType = PARENT;
break;
case 4:
userType = SCHOOL_ADMIN;
break;
default:
userType = UNKNOWN;
break;
}
return userType;
}
public String getDescription() {
String desc = null;
switch (this) {
case STUDENT:
desc = "学生";
break;
case TEACHER:
desc = "老师";
break;
case PARENT:
desc = "家长";
break;
case SCHOOL_ADMIN:
desc = "学校管理员";
break;
default:
desc = "未知用户";
break;
}
return desc;
}
}

现在,假设知道某个用户的类型值(int userType = ...),需要根据类型来进行某些业务处理。

很多人也许会尝试写下这样的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
UserType type = UserType.valueOf(userType);
switch (type) {
case UserType.STUDENT:
...
break;
case UserType.TEACHER:
...
break;
case UserType.PARENT:
...
break;
...
}

不幸的是,这样的写法根本连编译都通不过。

那有些人也许会尝试这样写:

1
2
3
4
5
6
7
8
9
10
11
12
switch (userType) {
case UserType.STUDENT.getValue():
...
break;
case UserType.TEACHER.getValue():
...
break;
case UserType.PARENT.getValue():
...
break;
...
}

可这样写同样是编译通不过,编译器会提示说 case 后面跟的必须是一个常量。

最后,万般无奈之下也许就会这样写了:

1
2
3
4
5
6
7
8
9
10
11
12
switch (userType) {
case 1:
...
break;
case 2:
...
break;
case 3:
...
break;
...
}

这样的写法其实是没有利用到枚举类型。虽然在语法和功能上是都对的,但是因为出现了 magic 数字,所以是很不规范的代码。如果以后用户类型的值需要调整的话,除了修改枚举类里定义的数字,这里的数字也得调整,所以代码维护性很差。

正确的写法应该是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
UserType type = UserType.valueOf(userType);
switch (type) {
case STUDENT:
...
break;
case TEACHER:
...
break;
case PARENT:
...
break;
...
}

即在 case 后面可以直接写枚举类型,不用加枚举类的类名。这样的写法看起来也比较简洁。