枚举Enum的使用

qchen
• 阅读 1532

1、为什么使用枚举?

以博客网站为例,文章有三种状态:草稿、审核和发布,可将其定义为静态常量:

public class BlogStatus{
    public static final int Draft = 1; // 草稿
    public static final int Review = 2; // 审核
    public static final int Published = 3; // 发布
}

对于一个判断函数judgeBlogStatus()而言,输入参数没有类型的约束,因此传入任意一个int值都是可以的,编译器也不会提出任何警告。

public void judgeBlogStatus(int status){
    ...
}

此时枚举类型就可以严谨地约束:

public enum BlogStatus{
    Draft, Review, Published
}
public void judgeBlogStatus(BlogStatus status){
    ...
}

2、如何使用Enum

以后台管理系统为例,使用枚举Enum定义用户角色:

public enum UserRole{
    ROLE_ROOT_ADMIN;    // 系统管理员
    ROLE_ORDER_ADMIN;   // 订单管理员
    ROLE_NORMAL;        // 普通用户
}

枚举的基本用法:

UserRole role1 = UserRole.ROLE_ROOT_ADMIN;
UserRole role2 = UserRole.ROLE_ORDER_ADMIN;
UserRole role3 = UserRole.ROLE_NORMAL;

// values()方法:返回所有枚举常量的数组集合
for(UserRole role : UserRole.values()){
    System.out.println(role);
}
// 打印:
// ROLE_ROOT_ADMIN
// ROLE_ORDER_ADMIN
// ROLE_NORMAL

// ordinal()方法:返回枚举常量的序数,注意从0开始
System.out.println( role1.ordinal() ); // 打印0
System.out.println( role2.ordinal() ); // 打印1
System.out.println( role3.ordinal() ); // 打印2

// compareTo()方法:枚举常量间的比较
System.out.println( role1.compareTo(role2) ); //打印-1
System.out.println( role2.compareTo(role3) ); //打印-2
System.out.println( role1.compareTo(role3) ); //打印-2

// name()方法:获得枚举常量的名称
System.out.println( role1.name() ); // 打印ROLE_ROOT_ADMIN
System.out.println( role2.name() ); // 打印ROLE_ORDER_ADMIN
System.out.println( role3.name() ); // 打印ROLE_NORMAL

// valueOf()方法:返回指定名称的枚举常量
System.out.println( UserRole.valueOf( "ROLE_ROOT_ADMIN" ) );
System.out.println( UserRole.valueOf( "ROLE_ORDER_ADMIN" ) );
System.out.println( UserRole.valueOf( "ROLE_NORMAL" ) );

switch语句中的Enum

UserRole userRole = UserRole.ROLE_ORDER_ADMIN;
switch (userRole) {
    case ROLE_ROOT_ADMIN:  // 枚举变量名称比1,2,3数字更好理解
        System.out.println("这是系统管理员角色");
        break;
    case ROLE_ORDER_ADMIN:
        System.out.println("这是订单管理员角色");
        break;
    case ROLE_NORMAL:
        System.out.println("这是普通用户角色");
        break;
}

3、自定义扩充枚举

扩充UserRole的枚举,加入“角色名——角色编码”的对应关系

public enum UserRole{
    ROLE_ROOT_ADMIN("系统管理员", 000000),
    ROLE_ORDER_ADMIN("订单管理员", 100000),
    ROLE_NORMAL("普通用户", 200000),
    ;

    // 自定义属性
    private final String roleName; // 角色名称
    privaye final Integer roleCode; // 角色编码

    // 自定义构造函数
    UserRole(String roleName, Integer roleCode){
        this.roleName = roleName;
        this.roleCode = roleCode;
    }

    // 自定义方法
    public String getRoleName() {
        return this.roleName;
    }

    public Integer getRoleCode() {
        return this.roleCode;
    }

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

从上述代码可知,在enum枚举类中完全可以像在普通Class里一样声明属性、构造函数以及成员方法。

4、枚举+接口的使用

以什么角色能干什么事为例,首先定义一个公用的接口RoleOperation,表示不同角色所能做的操作:

public interface RoleOperation{
    String op();
}

定义一个枚举类RoleEnum,依次实现RoleOperation接口:

public enum RoleEnum implements RoleOperation{
    // 系统管理员(有A操作权限)
    ROLE_ROOT_ADMIN{
        @Override
        public String op() {
            return"ROLE_ROOT_ADMIN:" + " has AAA permission";
        }
    },

    // 订单管理员(有B操作权限)
    ROLE_ORDER_ADMIN {
        @Override
        public String op() {
            return"ROLE_ORDER_ADMIN:" + " has BBB permission";
        }
    },

    // 普通用户(有C操作权限)
    ROLE_NORMAL {
        @Override
        public String op() {
            return"ROLE_NORMAL:" + " has CCC permission";
        }
    };
}

调用:

public class JudgeRole{
    public String judge(String roleName){
        // 一行代码搞定if/else判断不同角色
        return RoleEnum.valueOf(roleName).op();
    }
}

5、枚举与设计模式

1、单例模式

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;
    }
}

2、策略模式 使用枚举写一个基于策略模式的计算器

public class Test{

    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; // 乘法
            }
        },


        DIVISION {
            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 ) );
        // 打印 6.0
        System.out.println( Calculator.SUBTRACTION.execute( 4.0, 2.0 ) );
        // 打印 2.0
        System.out.println( Calculator.MULTIPLICATION.execute( 4.0, 2.0 ) );
        // 打印 8.0
        System.out.println( Calculator.DIVISION.execute( 4.0, 2.0 ) );
        // 打印 2.0
    }
}

6、枚举的集合类

1、EnumSet

public enum UserRole{
    ROLE_ROOT_ADMIN,  // 系统管理员

    ROLE_ORDER_ADMIN, // 订单管理员

    ROLE_NORMAL       // 普通用户
}

后台系统新增了一批人,现在需要查看他们是不是某个角色中的一个:

// 定义管理员角色的专属集合
EnumSet<UserRole> userRolesForAdmin = EnumSet.of(
    UserRole.ROLE_ROOT_ADMIN;
    UserRole.ROLE_ORDER_ADMIN;
);

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

2、EnumMap 系统里来了一批人,我们需要统计不同的角色到底有多少人:

Map<UserRole, Integer> userStatisticMap = new EnumMap<>(UserRole.class);
for(User user : userList){
    Integer num = userStatisticMap.get(user.getUserRole());
    if(num != num){
        userStatisticMap.put(user.getUserRole(), num + 1);
    }else{
        userStatisticMap.put(user.getUserRole(), 1);
    }
}
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
Java枚举的小知识点
enum是jdk1.5引入的,使用它可以创建枚举类型,就像使用class创建类一样。enum关键字创建的枚举类型默认是java.lang.Enum(一个抽象类)的子类用法1常量一般定义常量都是publicstaticfinal…,现在可以把相关常量都放在一个枚举类里,而且枚举比常量提供更多方法1.enumsea
Stella981 Stella981
2年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Easter79 Easter79
2年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
qchen
qchen
Lv1
谁家玉笛暗飞声,散入春风满洛城。
文章
4
粉丝
2
获赞
8