java中枚举表示数据状态
文章目录
- 1 场景
- 2 步骤
- 2.1 直接使用
- 2.1.1 优点
- 2.1.2 缺点
- 2.2 静态常量
- 2.2.1 优点
- 2.2.2 缺点
- 2.3 枚举
- 2.3.1 优点
- 2.3.2 缺点
- 2.4 枚举+命名空间
- 2.4.1 枚举基础接口
- 2.4.2 枚举实现类
- 2.4.3 枚举命名空间
- 2.4.3 使用
1 场景
本文主要讲下java程序中对于状态数据
的状态代码
和状态名称
如何管理的问题。
对于数据的状态,程序中,经常不会存储状态的名称
,而会存储状态对应的代码
。
每个java后端开发,面对数据库中的一个字段注释:
del_flag 删除状态(0:正常;1:删除;)
都会纠结一个问题,在java代码中,这个字段delFlag值
对应的0
和1
和分别对应的含义正常
、删除
,写在java代码的哪个地方比较合适?
很多人认为这个对于很大的项目来说无非是个很小的事,写在哪里,无所谓,都不会影响我们的项目。讲道理,这个无法反驳。
这篇文章,让我们一起剖析下这件微不足道的小事。
在这里,我们为了方便,定义状态代码
和状态名称
的类型均为字符串
。
2 步骤
2.1 直接使用
最简单的用法,就是直接在程序中使用
状态的代码
,如下。
//(1)设置删除标记为正常
record.setDelFlag("0");
......
//(2)判断删除标志
if("0".equals(record.getDelFlag())){return "正常";
}
2.1.1 优点
项目初期管理简单
,不用花费时间进行代码封装。
2.1.2 缺点
(1)项目中出现大量手写
的状态代码和状态名称。代码检查工具会提示魔法值
,如项目中对代码检查要求高,此部分代码无法合并主干代码。
(2)如果状态代码对应的状态名称发生了变动
,全局更改起来,将是十分致命的。
(3)研发人员水平不一致,手动在代码里写状态代码和状态名称,十分容易写错
。
2.2 静态常量
部分项目,会定义一个java类,将状态码定义为其中的静态常量
。其中定义了项目中用到的所有状态代码
。
public class StateContext{/*** 正常*/public static final String NORMAL="0";/*** 删除*/public static final String DEL="1";//其他状态代码......
}
静态常亮的使用方式如下:
//(1)设置删除标记为正常
record.setDelFlag(StateContext.NORMAL);
......
//(2)判断删除标志
if(StateContext.NORMAL.equals(record.getDelFlag())){return "正常";
}
2.2.1 优点
状态代码
,可以直接通过类的静态变量使用(状态名称
,也可以通过类的静态变量定义)。
2.2.2 缺点
(1)需要在类中大量定义静态变量,使用时,需十分明确使用的变量的名字,勿使用成别的变量。
(2)一般只通过静态变量定义状态代码
,状态名称
也可这么定义。使用时,对应关系容易对应不上。
2.3 枚举
每种状态信息,定义专门的枚举类。
/*** 删除标志枚举*/
public enum DelFlagEnum{NORMAL("0","正常"),DEL("1","删除");private DelFlagEnum(String code,String name){this.code=code;this.name=name;}/*** 代码*/private String code;/*** 名称*/private String name;public String getCode() {return code;}public String getName() {return name;}}
2.3.1 优点
(1)每种状态定义一个专门的枚举类,枚举类中的定义十分明确
。
(2)可通过枚举属性准确
对应的状态代码和状态名称。
(3)定义的枚举是有属性的
,可以在枚举中定义专门的特殊方法,应对特殊的业务。
2.3.2 缺点
枚举主动在代码中使用,是没有问题的。如下:
DelFlagEnum.NORMAL.getCode();
但是状态代码
一般都会存储在数据库中
,如果通过数据库中获取的状态代码获取枚举对象
,基础的枚举信息,无法实现此功能。
故可以在枚举中,定义专门
的方法,通过状态代码
获取枚举
或通过状态名称
获取枚举
。如下
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.List;/*** 删除标志枚举*/
public enum DelFlagEnum{NORMAL("0","正常"),DEL("1","删除");private DelFlagEnum(String code,String name){this.code=code;this.name=name;}/*** 枚举集合*/private static final List<DelFlagEnum> ENUM_LIST= EnumUtils.getEnumList(DelFlagEnum.class);/*** 通过代码获取枚举* @param code 枚举代码* @return 枚举*/public static DelFlagEnum getEnumByCode(String code){if(StringUtils.isNotEmpty(code) && CollectionUtils.isNotEmpty(ENUM_LIST)){for(DelFlagEnum delFlagEnum:ENUM_LIST){if(code.equals(delFlagEnum.getCode())){return delFlagEnum;}}}return null;}/*** 通过名称获取枚举* @param name 枚举名称* @return 枚举*/public static DelFlagEnum getEnumByName(String name){if(StringUtils.isNotEmpty(name) && CollectionUtils.isNotEmpty(ENUM_LIST)){for(DelFlagEnum delFlagEnum:ENUM_LIST){if(name.equals(delFlagEnum.getName())){return delFlagEnum;}}}return null;}/*** 代码*/private String code;/*** 名称*/private String name;public String getCode() {return code;}public String getName() {return name;}
}
但是,如果每个枚举都是这样写。代码量大大增加
,极易出现拷贝导致的低级错误
。因此需对此代码进行封装
,减少开发人员的工作量。
2.4 枚举+命名空间
此种方式,是对2.3中枚举定义状态值进行了代码封装
。
这是作者当前找到的最优的方式,建议使用。
2.4.1 枚举基础接口
定义基础枚举接口。接口中定义枚举中必有的两个方法(获取代码、获取名称)
public interface BaseEnum {/*** 获取代码* @return*/String getCode();/*** 获取名称* @return*/String getName();
}
2.4.2 枚举实现类
每种状态对应专门的枚举类
,每个枚举类均需实现接口BaseEnum
(javac编译器,枚举无法继承,所以成员变量、接口方法,还需要手动写)。
枚举类中仍然可以定义专门的方法,来执行特殊业务。
public enum DelFlagEnum implements BaseEnum{NORMAL("0","正常"),DEL("1","删除");/*** 代码*/private String code;/*** 名称*/private String name;private DelFlagEnum(String code, String name){this.code=code;this.name=name;}@Overridepublic String getCode() {return this.code;}@Overridepublic String getName() {return this.name;}
}
2.4.3 枚举命名空间
可以通过此命名空间实现如下功能:
(1)通过代码获取枚举(时间复杂度O(1))
(2)通过名称获取枚举(时间复杂度O(n))
上述两个方法均线程安全
,且均为懒加载
,即用到方法时才去初始化对应的枚举类缓存。
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** 枚举命名空间*/
public class EnumContext {/*** 枚举集合映射*/private static final Map<String, Map<String, BaseEnum>> ENUM_MAP = new ConcurrentHashMap<>();/*** 初始化枚举map*/private synchronized static <T extends BaseEnum> void initEnumMap(Class<T> enumClass) {if (enumClass != null && enumClass.isEnum()) {String key = enumClass.getName();if (!ENUM_MAP.containsKey(key)) {Map<String, BaseEnum> map = new ConcurrentHashMap<>();BaseEnum[] baseEnums = enumClass.getEnumConstants();if (baseEnums != null && baseEnums.length > 0) {for (final BaseEnum e : baseEnums) {map.put(e.getCode(), e);}}ENUM_MAP.put(key, map);}}}/*** 通过代码获取枚举(时间复杂度O(1))** @param code 代码* @param enumClass 枚举类* @return 枚举*/public static <T extends BaseEnum> T getEnumByCode(String code, Class<T> enumClass) {if (StringUtils.isNotEmpty(code) && enumClass != null) {String key = enumClass.getName();if (!ENUM_MAP.containsKey(key)) {//如果不存在=>初始化initEnumMap(enumClass);}//如果已存在=>判断Map<String, BaseEnum> map = ENUM_MAP.get(key);if (MapUtils.isNotEmpty(map)) {return (T) map.get(code);}}return null;}/*** 通过名称获取枚举(时间复杂度O(n))** @param name 代码* @param enumClass 枚举类* @return 代码*/public static <T extends BaseEnum> T getEnumCodeByName(String name, Class<T> enumClass) {if (StringUtils.isNotEmpty(name) && enumClass != null) {String key = enumClass.getName();if (!ENUM_MAP.containsKey(key)) {//如果不存在=>初始化initEnumMap(enumClass);}//如果已存在=>判断Map<String, BaseEnum> map = ENUM_MAP.get(key);if (MapUtils.isNotEmpty(map)) {for (Map.Entry<String, BaseEnum> entry : map.entrySet()) {if (entry.getValue() != null && name.equals(entry.getValue().getName())) {return (T) entry.getValue();}}}}return null;}
}
2.4.3 使用
//直接使用枚举
System.out.println(DelFlagEnum.NORMAL.getCode() + " " + DelFlagEnum.NORMAL.getCode());//通过代码获取枚举
DelFlagEnum normalEnum = EnumContext.getEnumByCode("0", DelFlagEnum.class);
if (normalEnum != null) {System.out.println(normalEnum.getCode() + " " + normalEnum.getName());
}//通过名称获取枚举
DelFlagEnum delEnum = EnumContext.getEnumCodeByName("删除", DelFlagEnum.class);
if (delEnum != null) {System.out.println(delEnum.getCode() + " " + delEnum.getName());
}
java中枚举表示数据状态相关推荐
- Java 中的面向数据编程
近年来, Amber项目为 Java 带来了许多新特性-- 局部变量类型推断. 文本块. 记录类. 封印类. 模式匹配 等等.虽然这些特性都是独立的,但也可以组合在一起使用.具体地说,记录类.封印类和 ...
- java培训教程分享:Java中怎样将数据对象序列化和反序列化?
本期为大家介绍的java培训教程是关于"Java中怎样将数据对象序列化和反序列化?"的内容,相信大家都知道,程序在运行过程中,可能需要将一些数据永久地保存到磁盘上,而数据在Java ...
- java中map转为json数据_Java技术-将java中Map类型数据转化为json数据并以Ajax形式返回...
Java技术-将java中Map类型数据转化为json数据并以Ajax形式返回html 1.自定义工具类(简单易用)-下面是我写的一个简单的工具类前端 package com.test.util; i ...
- Java中枚举的线程安全性及序列化问题
转载自 Java中枚举的线程安全性及序列化问题 Java SE5提供了一种新的类型-Java的枚举类型,关键字enum可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序 ...
- java基础----Java中枚举的使用(一)
这里介绍一下java中关于枚举的使用. java中枚举的使用 一.枚举中可以定义方法 参照于TimeUnit的使用,TimeUnit.MILLISECONDS.sleep(1000); LoveUti ...
- Java中判断当前数据是否全为数字
Java中判断当前数据是否全为数字 总共又三种方法 一.用JAVA自带的函数编写判断机制 二.用正则表达式编写判断机制 三.用ascii码编写判断机制 总共又三种方法 一.用JAVA自带的函数编写判断 ...
- Java中使用JSON数据传递
一.Java中使用JSON数据传递 pom依赖引入 <dependency><groupId>com.alibaba</groupId><artifactId ...
- 操作系统中进程的五种状态与JAVA中线程的六种状态
操作系统中的五种状态 新建:创建新的进程 就绪:进程已经获得除CPU时间片以外的任何资源,一旦获得cpu时间片就能立马执行. 执行:处于就绪队列中的进程获得了时间片运行进程. 阻塞:进程时间片用完进入 ...
- 19、java中枚举
枚举是什么? 枚举就是将一个有限集合中的所有元素列举出来,在java中使用可以使用enum关键字来声明一个枚举类. 为什么使用枚举? 之前当用到一些常量时,便临时声明一个,这样使得代码看起来很乱,这里 ...
最新文章
- 关于oracle的基础增删改查操作总结
- 广播代码_代码广播:专为编码而设计的24/7音乐
- Linux Kernel 3.0新特性概览(转)
- 霍尔电流传感器ACS712的性能参数和用法
- Windows 10企业批量部署实战之刷新并添加启动映像
- javaWeb项目带红色感叹号问题原因
- android 监听 h5 window,H5嵌入APP后,通过window.WebViewJavascriptBridge原生APP与H5之间交互...
- CetnOS 6.7安装Hive 1.2.1
- ZOJ Problem Set - 1292 Integer Inquiry
- 计算机二级c语言必看,计算机二级C语言考试必看技巧
- win10c语言关机,win10电脑自动关机命令
- 高通芯片资料下载大全,这是一个资料下载论坛
- 正式“退休”的Flash,未来我们会怀念它吗?
- 5G移动通信网络构架与关键技术要点探讨
- 计算机第十三套试题,2012年计算机二级VB第十三套上机试题及解析
- 邮箱客户端程序的实现
- 全屏背景图移动端滚动时白底问题
- Vue中图片加载问题总结
- Ubuntu / Python / Mega自动同步监控照片
- 【算法基础四】C语言小项目实战---通讯录管理系统(单链表)
热门文章
- 2021年8月上中旬好文收藏(1)
- 为什么系统调用会消耗较多资源?系统调用的三种方法:软件中断(分析过程)、SYSCALL指令、vDSO(虚拟动态链接对象linux-vdso.so.1)
- srsLTE源码学习:RLC,无线链路控制子层抓包rlc_pcap.h,rlc_pcap.cc
- 排序算法:归并排序(C、Java)
- java的值排序总结
- java 线程锁概念_Java多线程——锁概念与锁优化
- oracle adg 人工干预,Oracle DataGuard
- Cron表达式的正则表达式
- 微信开源推理加速工具 TurboTransformers,性能超越 PyTorch/TensorFlow 与主流优化引擎
- OpenJS 基金会推出 Node.js 证书,JS 开发者可以“考证”了