工作中很少使用枚举类,每次想用的时候总是偷懒使用直接定义常量的方式了,今天有时间好好探究下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 () { for (User user : User.values()) { System.out.println(user); } System.out.println(user1.ordinal()); System.out.println(user2.ordinal()); System.out.println(user3.ordinal()); System.out.println(user1.compareTo(user2)); System.out.println(user2.compareTo(user3)); System.out.println(user1.compareTo(user3)); System.out.println(user1.name()); System.out.println(user2.name()); System.out.println(user3.name()); 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 )); } }
专门用用于枚举的集合类
EnumSet和EnumMap
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 ); } } } }