Java - Enum小结

工作中很少使用枚举类,每次想用的时候总是偷懒使用直接定义常量的方式了,今天有时间好好探究下Enum.
为什么我们需要枚举类
以学生管理系统的权限管理为例,该系统管理员一般有3个权限类名:系统管理员,教师,学生,我们可以将其定义为静态常量:

1
2
3
public static final int Student = 1;	//学生
public static final int Teacher = 2; //教师
public static final int Admin = 3; //管理员

这种直接常量的方式定义本身没有问题,但是缺少了约束,存在安全隐患。

1
2
3
void judgeUser(int user){
...
}

比如这个方法是判断传入的用户类型,但是在调用该方法时,开发者时可以传入任意的值,并无限制。
现在我们就要切换到Enum的方式,我们刚好对比下有什么值得我们update的地方。

1
2
3
4
5
public enum User {
ROLE_ADMIN,
ROLE_TEACHER,
ROLE_STUDENT
}

接下来我们就用这个User为例先看看枚举类的基本用法有那些?

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
public class UserSIT {
User user1 = User.ROLE_ADMIN;
User user2 = User.ROLE_TEACHER;
User user3 = User.ROLE_STUDENT;

@Test
public void enum_testcae() {
//value()方法:返回所有枚举常量的数组集合
for (User user : User.values()) {
System.out.println(user);
}
//打印:
//ROLE_ADMIN
//ROLE_TEACHER
//ROLE_STUDENT

//ordinal()方法:返回枚举常量的序数,从0开始
System.out.println(user1.ordinal());//打印0
System.out.println(user2.ordinal());//打印1
System.out.println(user3.ordinal());//打印2

//compareTo()方法:枚举常量间的比较
//调用compareTo方法返回的结果,正值代表方法中参数在调用该方法的枚举对象位置之前
//0代表两个成员在相同的位置;
//负值代表方法中参数在调用该方法的枚举对象位置之后
System.out.println(user1.compareTo(user2));//打印-1
System.out.println(user2.compareTo(user3));//打印-1
System.out.println(user1.compareTo(user3));//打印-2

//name()方法:获得枚举常量的名称
System.out.println(user1.name());//打印ROLE_ADMIN
System.out.println(user2.name());//打印ROLE_TEACHER
System.out.println(user3.name());//打印ROLE_STUDENT

//valueOf()方法:返回指定名称的枚举常量
System.out.println(User.valueOf("ROLE_ADMIN"));
System.out.println(User.valueOf("ROLE_TEACHER"));
System.out.println(User.valueOf("ROLE_STUDENT"));

}
}

除此之外,枚举类也可以用在switch中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void enum_testcase_002() {
User user = User.ROLE_ADMIN;
switch (user) {
case ROLE_ADMIN:
System.out.println("管理员");
break;
case ROLE_TEACHER:
System.out.println("教师");
break;
case ROLE_STUDENT:
System.out.println("学生");
break;
}
}

当然枚举也存在多值的用法:

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
public enum UserRole {
ROLE_ROOT_ADMIN("系统管理员", 000000),
ROLE_ORDER_ADMIN("订单管理员", 100000),
ROLE_NORMAL("普通用户", 20000),
;
private final String roleName;
private final Integer roleCode;

public String getRoleName() {
return roleName;
}

public Integer getRoleCode() {
return roleCode;
}

UserRole(String roleName, Integer roleCode) {
this.roleName = roleName;
this.roleCode = roleCode;
}

public static Integer getRoleNameByRoleName(String roleName) {
for (UserRole enums : UserRole.values()) {
if (enums.getRoleName().equals(roleName)) {
return enums.getRoleCode();
}
}
return null;

}
}

枚举也有一些其他的用法:
比如枚举+接口

1
2
3
public interface RoleOperstion {
String op();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public enum RoleEnum implements RoleOperstion {
ROLE_ROOT_ADMIN {
@Override
public String op() {
return null;
}
},
ROLE_ORDER_ADMIN {
@Override
public String op() {
return null;
}
},
ROLE_NORMAL {
@Override
public String op() {
return null;
}
};
}

我们再看看如何调用:

1
2
3
4
5
public class judgeRole {
public String judge(String roleName){
return RoleEnum.valueOf(roleName).op();
}
}

这样的方式就可以避免if/else的大量使用。
还有枚举和设计模式的结合

  • 单例模式
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
public class Singleton {

//构造函数私有化,避免外部创建实例
private Singleton(){}

//定义一个内部枚举
public enum SingletonEnum{
SEED; //唯一一个枚举对象

private Singleton singleton;

SingletonEnum(){
singleton = new Singleton(); //真正的对象创建隐藏再这里
}

public Singleton getInstance(){
return singleton;
}
}

//故意外露的对象获取方法,也是外边获取实例的唯一入口
public static Singleton getInstance(){
return SingletonEnum.SEED.getInstance(); //通过枚举类来完成
}

  • 策略模式
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
public class Demo {
public enum Calculator {
ADDITION {
public Double execute(Double x, Double y) {
return x + y;
}
},
SUBTRACTION {
public Double execute(Double x, Double y) {
return x - y;
}
},
MULTIPLICATION {
public Double execute(Double x, Double y) {
return x * y;
}
},
DIVSION {
public Double execute(Double x, Double y) {
return x / y;
}
};

public abstract Double execute(Double x, Double y);
}

public static void main(String[] args) {
System.out.println(Calculator.ADDITION.execute(4.0, 2.0));
System.out.println(Calculator.SUBTRACTION.execute(4.0, 2.0));
System.out.println(Calculator.MULTIPLICATION.execute(4.0, 2.0));
System.out.println(Calculator.DIVSION.execute(4.0, 2.0));
}
//console print:
//6.0
//2.0
//8.0
//2.0
}
  • 专门用用于枚举的集合类

    EnumSet和EnumMap

  1. EnumSet
1
2
3
4
5
public enum UserRole {
ROLE_ROOT_ADMIN,
ROLE_ORDER_ADMIN,
ROLE_NORMAL
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Test
public void testcase_001() {
//定义一个管理员角色的专属集合
EnumSet<UserRole> userRolesForAdmin
= EnumSet.of(
UserRole.ROLE_ROOT_ADMIN,
UserRole.ROLE_ORDER_ADMIN
);

//判断某个进来的用户是不是管理员
Boolean isAdmin(User user){
if(userRolesForAdmin.contains(user.getUserRole)){
return true;
}else {
return false;
}
}
}

​ 2.EnumMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class SIT {
//比如系统新进入的一些人,我们需要统计下不同的角色到底有多少人
@Test
public void testcase_002() {
Map<UserRole,Integer> userRoleIntegerMap = new EnumMap<UserRole, Integer>(UserRole.class);
for(User user : userList){
Integer num = userRoleIntegerMap.get(user.getUserRole());
if(null!=num){
userRoleIntegerMap.put(user.getUserRole(),num+1);
}else{
userRoleIntegerMap.put(user.getUserRole(),1);
}
}
}
}

Java - Enum小结
https://skynetboys.github.io/2020/03/21/Java-Enum小结/
Author
Edison
Posted on
March 21, 2020
Licensed under