在项目实际开发过程中, 经常会遇到对某些固定的值, 字典项的定义的需求, 很多项目经常使用常量来定义, 其实在 jdk1.5 就已经引入了枚举, 使用枚举可以更好的解决这类需求, 本文主要记录枚举的优势以及经常在项目中使用的方法.
知识点
枚举类命名
枚举类的命名通常需要 Enum 为后缀, 枚举成员名称需要全大写, 单词间用下划线隔开.
枚举类不允许使用 extends 关键字
枚举类默认会继承 java.lang.Enum, 由于 java 是单继承, 所以在定义枚举类时不允许再继承其他类, 但可以实现多个接口
枚举的比较可以直接使用 ==
枚举是不允许被 new 出来的, 枚举类里的构造函数都限定为私有化, 是不允许使用 public 定义构造函数的. 枚举的赋值, 如果是同一个元素, 则会指向同一个地址, 所以是可以直接使用 == 的, 当然在 Enum 类中, 重写了 equals 方法 (如下图), 所以也是可以用 equals 来判断.
枚举常用方法
方法名 | 用途 |
---|---|
name() | 返回枚举常量名 |
toString() | 返回枚举常量名 |
values() | 返回枚举成员数组 |
valueOf() | 通过枚举常量名返回枚举 |
ordinal() | 返回枚举常量在 enum 声明中的位置,位置是从 0 开始计数的 |
枚举在 switch 中的使用
枚举在 switch 中的使用, 优势在于能控制 case 的范围 (看以下实例), 并且在 idea 中有相关提示
枚举在单例模式的使用
首先使用枚举类实现单例模式, 写法相当简单, 看最后的实例; 其次枚举是线程安全, 单一实例 (由于构造方法都是私有的, 不能被 new)
实例
1. 最简单的枚举
在项目中经常会遇到一些固定值的定义, 以往都是用常量来定义, 以下用实例说明, 为啥枚举的方式优于常量的方式, 以下就以季节的定义为例
1.1 使用常量来实现
- /**
- * @Description: 季节常量定义
- */
- public class SeasonConst {
- /**
- * 春季
- */
- public static final String SPRING = "SPRING";
- /**
- * 夏季
- */
- public static final String SUMMER = "SUMMER";
- /**
- * 秋季
- */
- public static final String AUTUMN = "AUTUMN";
- /**
- * 冬季
- */
- public static final String WINTER = "WINTER";
- }
以上实例虽然实现了功能, 但有两点比较明显的缺点:
常量值容易写错 (特别是复制黏贴, 但是忘记改对应的值, 导致系统出 bug),idea 不会给任何提示.
比如, 某人粗心, 在复制黏贴代码时变成 (将春季, 夏季都定义成春季了):
- /**
- * 春季
- */
- public static final String SPRING = "SPRING";
- /**
- * 夏季
- */
- public static final String SUMMER = "SPRING";
如果我想知道一年总共多少个季节, 咋整? 用常量定义的类, 有点捉襟见肘
1.2 使用枚举来实现, 可以实现常量的所有功能, 并能轻松解决以上提出的常量的两个缺点
定义枚举类 SeasonEnum
- public enum SeasonEnum {
- /**
- * 春季
- */
- SPRING,
- /**
- * 夏季
- */
- SUMMER,
- /**
- * 秋季
- */
- AUTUMN,
- /**
- * 冬季
- */
- WINTER
- }
在 SeasonEnum 枚举类中, 如果定义两个 SPRING, 编译器会直接报错, 很好解决了常量的第一个缺点
该枚举类的使用 (1, 获取枚举值的名称; 2, 枚举判断的使用; 3, 枚举循环的使用. 通过枚举的循环, 很好解决了常量的第二个缺点;)
- // 获取枚举值的名称, 与 toString 得到的结果一样
- String spring = SeasonEnum.SPRING.name();
- System.out.println(spring);
- // 枚举判断的使用
- SeasonEnum springEnum1 = SeasonEnum.SPRING;
- SeasonEnum springEnum2 = SeasonEnum.SPRING;
- SeasonEnum summerEnum3 = SeasonEnum.SUMMER;
- // 由于 springEnum1,springEnum2 都指向 SPRING, 所以输出 true
- System.out.println("springEnum1 == springEnum2:" + (springEnum1 == springEnum2));
- // 由于 springEnum1 指向 SPRING,summerEnum3 指向 SUMMER, 所以输出 false
- System.out.println("springEnum1 == summerEnum3:" + (springEnum1 == summerEnum3));
- // 循环枚举, 打印枚举类中的所有枚举成员
- SeasonEnum[] seasonEnums = SeasonEnum.values();
- for (SeasonEnum seasonEnum : seasonEnums) {
- System.out.println(seasonEnum.name());
- }
枚举在 switch 中的使用, 如果 case 后跟不存在 SeasonEnum 类中的枚举 (比如 case OTHER), 则编译器会报错
- String enumName = "SPRING";
- SeasonEnum seasonEnum = SeasonEnum.valueOf(enumName);
- switch (seasonEnum){
- case SPRING:
- System.out.println(seasonEnum.name());
- break;
- case SUMMER:
- System.out.println(seasonEnum.name());
- break;
- case AUTUMN:
- System.out.println(seasonEnum.name());
- break;
- case WINTER:
- System.out.println(seasonEnum.name());
- break;
- default:
- System.out.println("other");
- }
2. 在枚举中使用自定义属性和方法
项目中经常也会遇到一些字典项的定义, 比如性别, 包含存入数据库中的值, 以及显示在页面上的值. 以下通过实例来实现性别字典.
定义 SexEnum(注意看代码中的注解)
- public enum SexEnum {
- MAN("man","男"),
- WOMEN("women","女");
- private String sexCode;
- private String sexName;
- /**
- * 自定义构造函数, 以完成枚举对 sexCode,sexName 赋值
- * @param sexCode
- * @param sexName
- */
- SexEnum(String sexCode,String sexName){
- this.sexCode = sexCode;
- this.sexName = sexName;
- }
- /**
- * 获取 sexCode
- * @return
- */
- public String getSexCode() {
- return sexCode;
- }
- /**
- * 获取 sexName
- * @return
- */
- public String getSexName() {
- return sexName;
- }
- /**
- * 项目中经常会根据 code, 转换成对应的 name
- * 所以这里自定义方法, 根据 sexCode 获取 sexName
- * 通过循环 enum 来实现
- * @param sexCode
- * @return
- */
- public static String getSexNameByCode(String sexCode){
- String sexName = "sexCode 不存在";
- SexEnum[] sexEnums = SexEnum.values();
- for (SexEnum sexEnum : sexEnums) {
- if(sexEnum.getSexCode().equals(sexCode)){
- sexName = sexEnum.getSexName();
- break;
- }
- }
- return sexName;
- }
- /**
- * 项目中也有根据 name, 转换成对应的 code
- * 所以这里自定义方法, 根据 sexName 获取 sexCode
- * 通过循环 enum 来实现
- * @param sexName
- * @return
- */
- public static String getSexCodeByName(String sexName){
- String sexCode = "sexName 不存在";
- SexEnum[] sexEnums = SexEnum.values();
- for (SexEnum sexEnum : sexEnums) {
- if(sexEnum.getSexName().equals(sexName)){
- sexCode = sexEnum.getSexCode();
- break;
- }
- }
- return sexCode;
- }
- /**
- * 根据 sexCode 获取 SexEnum, 在 switch 中使用
- * 通过循环 enum 来实现
- * @param sexCode
- * @return
- */
- public static SexEnum getEnumByCode(String sexCode){
- SexEnum[] sexEnums = SexEnum.values();
- for (SexEnum sexEnum : sexEnums) {
- if(sexEnum.getSexCode().equals(sexCode)){
- return sexEnum;
- }
- }
- return null;
- }
- /**
- * 重写 toString 方法
- * @return
- */
- @Override
- public String toString() {
- return this.sexCode + ":" + this.sexName;
- }
- }
SexEnum 枚举类的使用
- public class EnumMain {
- public static void main(String[] args){
- // 循环带自定义方法的枚举
- SexEnum[] sexEnums = SexEnum.values();
- for (SexEnum sexEnum : sexEnums) {
- System.out.println("sexCode:"+sexEnum.getSexCode());
- System.out.println("sexName:"+sexEnum.getSexName());
- System.out.println("sexCode:sexName="+sexEnum.toString());
- }
- // 根据 sexCode 获取 sexName
- String sexName = SexEnum.getSexNameByCode("women");
- System.out.println("根据 sexCode 获取 sexName:" + sexName);
- // 根据 sexName 获取 sexCode
- String sexCode = SexEnum.getSexCodeByName("男");
- System.out.println("根据 sexName 获取 sexCode:" + sexCode);
- // 通过传入的 sexCode 使用 switch
- testSexEnumSwitch("women");
- }
- /**
- * 实际项目中, 基本上都是传 sexCode 的, 所以这里也根据传入的 sexCode, 使用 switch 方法
- * @param sexCode
- */
- private static void testSexEnumSwitch(String sexCode){
- // 自定义 getEnumByCode 方法, 通过 sexCode 获取 SexEnum
- SexEnum sexEnum = SexEnum.getEnumByCode(sexCode);
- switch (sexEnum){
- case MAN:
- System.out.println(sexEnum.toString());
- break;
- case WOMEN:
- System.out.println(sexEnum.toString());
- break;
- default:
- System.out.println("other");
- }
- }
- }
3. 通过枚举实现单例
单例定义
- public enum Singleton {
- INSTALL;
- /**
- * 自定义方法
- */
- public void yourMethod(){
- System.out.println("do your business");
- }
- }
调用方法
Singleton.INSTALL.yourMethod();
源码获取
以上示例都可以通过我的 GitHub https://github.com/simonxie/javase-demo 获取完整的代码, 点击获取
来源: https://www.cnblogs.com/mingsay/p/12390900.html