Java根据code获取枚举优化方式

 更新时间:2026年03月02日 10:05:31   作者:丁花不是花  
文章介绍了如何优化枚举类根据code获取枚举类型的过程,通过创建基接口BaseEnum和枚举工具类MyEnumUtil,实现了通用的获取方法,同时,还讨论了根据description获取枚举的优化方法,并建议使用第二种方法

需求

自己模拟两个枚举,假设业务中需要用到

Example1StatusEnum.java

package com.zdh.zdhenum;

/**
 * @author dh
 * @date 2024/07/24
 * @desc (详细信息)
 */
public enum Example1StatusEnum {
    NEW("new", "新建状态"),
    FAIL("fail", "失败状态"),
    SUCCESS("success", "成功状态"),
    CLOSED("closed", "关闭状态");

    private String code;

    private String description;

    Example1StatusEnum(String code, String description) {
        this.code = code;
        this.description = description;
    }
}

Example2StatusEnum .java

package com.zdh.zdhenum;

import com.fasterxml.jackson.databind.ser.Serializers;

/**
 * @author dh
 * @date 2024/07/24
 * @desc (详细信息)
 */
public enum Example2StatusEnum implements BaseEnum {
    NEW("new", "新建状态"),
    FAIL("fail", "失败状态"),
    SUCCESS("success", "成功状态"),
    PROCESSING("processing", "处理中状态"),
    WAITING("waiting", "等待状态"),
    CLOSED("closed", "关闭状态"),
    ABANDONED("abandoned", "弃状态");

    private String code;

    private String description;

    Example2StatusEnum(String code, String description) {
        this.code = code;
        this.description = description;
    }

}

实际场景中,可能远远大于2个,每个枚举类内item有唯一的code,实际业务开发中需要根据唯一的code获取对应的枚举类型。

原始解决方案

哪个枚举类需要根据code获取对应的枚举,就在该枚举类中添加获取方法

例如Example1StatusEnum 需要根据code获取对应的枚举,在Example1StatusEnum 添加如下方法:

public static Example1StatusEnum  toEnum(String code){
        for (Example1StatusEnum item : Example1StatusEnum.values()) {
            if (Objects.equals(item.getCode(),code)) {
                return item;
            }
        }
        return null;
    }

同理,其他需要用到此方法,都需要复制上面的方法,并更改为对应类型,大量重复性工作。

优化方案

1. 首先创建base接口。

package com.zdh.zdhenum;

/**
 * @author dh
 * @date 2024/07/23
 * @desc (详细信息)
 */
public interface BaseEnum {
    /**
     * 获取code
     * @return
     */
    String getCode();
}

后面工具类根据此接口方法可以 通用的获取code

2. 创建枚举工具类

package com.zdh.zdhenum;

import java.util.Objects;

/**
 * @author dh
 * @date 2024/07/24
 * @desc (详细信息)
 */
public class MyEnumUtil {

    public static <E extends Enum<E> & BaseEnum> E toEnumByCode(String code, Class<E> enumClass) {
        for (E enumConstant : enumClass.getEnumConstants()) {
            if (Objects.equals(enumConstant.getCode(),code)) {
                return enumConstant;
            }
        }
        return null;
    }
}

<E extends Enum<E> & BaseEnum> 这里泛型,extends 表现必须继承自后面的xxx,BaseEnum规定必须实现上面定义的BaseEnum接口,Enum<E> 为枚举类的公共父类,规定必须是枚举类可以用此方法。

3. 需要使用工具类的枚举,实现BaseEnum接口即可

例如,Example1StatusEnumExample2StatusEnum都需要使用。

分别修改如下:

package com.zdh.zdhenum;

import java.util.Objects;

/**
 * @author dh
 * @date 2024/07/24
 * @desc (详细信息)
 */
public enum Example1StatusEnum implements BaseEnum{
    NEW("new", "新建状态"),
    FAIL("fail", "失败状态"),
    SUCCESS("success", "成功状态"),
    CLOSED("closed", "关闭状态");

    private String code;

    private String description;

    Example1StatusEnum(String code, String description) {
        this.code = code;
        this.description = description;
    }

    /**
     * 获取code
     *
     * @return
     */
    @Override
    public String getCode() {
        return this.code;
    }

}

package com.zdh.zdhenum;

import com.fasterxml.jackson.databind.ser.Serializers;

/**
 * @author dh
 * @date 2024/07/24
 * @desc (详细信息)
 */
public enum Example2StatusEnum implements BaseEnum {
    NEW("new", "新建状态"),
    FAIL("fail", "失败状态"),
    SUCCESS("success", "成功状态"),
    PROCESSING("processing", "处理中状态"),
    WAITING("waiting", "等待状态"),
    CLOSED("closed", "关闭状态"),
    ABANDONED("abandoned", "弃状态");

    private String code;

    private String description;

    Example2StatusEnum(String code, String description) {
        this.code = code;
        this.description = description;
    }

    /**
     * 获取code
     *
     * @return
     */
    @Override
    public String getCode() {
        return this.code;
    }
}

4. 测试使用

    public static void main(String[] args) {
        Example1StatusEnum quotaStatusEnum11 = MyEnumUtil.toEnumByCode("new", Example1StatusEnum.class);
        System.out.println("quotaStatusEnum11 = " + quotaStatusEnum11);
        Example1StatusEnum quotaStatusEnum12 = MyEnumUtil.toEnumByCode("fda", Example1StatusEnum.class);
        System.out.println("quotaStatusEnum12 = " + quotaStatusEnum12);

        Example2StatusEnum quotaStatusEnum21 = MyEnumUtil.toEnumByCode("new", Example2StatusEnum.class);
        System.out.println("quotaStatusEnum11 = " + quotaStatusEnum21);
        Example2StatusEnum quotaStatusEnum22 = MyEnumUtil.toEnumByCode("fda", Example2StatusEnum.class);
        System.out.println("quotaStatusEnum12 = " + quotaStatusEnum22);
    }

为了方便查看效果,可以在最后打个断点。

查看结果,发现和预期一样

拓展

假设,可能需要根据description 获取枚举,实际场景可能遇不到,重点在于思想。

那么几种解决方案:

  1. 原有的BaseEnum接口上加一个String getDescription(),然后MyEnumUtil 中添加一个和toEnumByCode类似的方法,泛型中依然使用BaseEnum。
  2. 新建一个接口BaseDescEnum,里面就一个String getDescription()方法。然后MyEnumUtil 中添加一个和toEnumByCode类似的方法,泛型中使用新的BaseDescEnum。

这里我建议使用第2种方法,这样颗粒度更细。第1种就算不需要根据description 获取枚举,也要实现String getDescription方法(虽然1.8之后可以通default关键字在接口默认实现,但是个人不太建议此场景这么使用)。

下面简单说一下实现。

新增BaseDescEnum接口

package com.zdh.zdhenum;

/**
 * @author dh
 * @date 2024/07/23
 * @desc (详细信息)
 */
public interface BaseDescEnum {
    /**
     * 获取description
     * @return
     */
    String getDescription();
}

假设仅仅Example1StatusEnum需要,代码修改如下:

package com.zdh.zdhenum;

import java.util.Objects;

/**
 * @author developer_ZhangXinHua
 * @date 2024/07/24
 * @desc (详细信息)
 */
public enum Example1StatusEnum implements BaseEnum,BaseDescEnum{
    NEW("new", "新建状态"),
    FAIL("fail", "失败状态"),
    SUCCESS("success", "成功状态"),
    CLOSED("closed", "关闭状态");

    private String code;

    private String description;

    Example1StatusEnum(String code, String description) {
        this.code = code;
        this.description = description;
    }

    /**
     * 获取code
     *
     * @return
     */
    @Override
    public String getCode() {
        return this.code;
    }


    /**
     * 获取description
     *
     * @return
     */
    @Override
    public String getDescription() {
        return this.description;
    }
}

MyEnumUtil中添加如下方法

  public static <E extends Enum<E> & BaseDescEnum> E toEnumByDesc(String desc, Class<E> enumClass) {
        for (E enumConstant : enumClass.getEnumConstants()) {
            if (Objects.equals(enumConstant.getDescription(),code)) {
                return enumConstant;
            }
        }
        return null;
    }

调用

public static void main(String[] args) {
        Example1StatusEnum quotaStatusEnum11 = MyEnumUtil.toEnumByCode("new", Example1StatusEnum.class);
        System.out.println("quotaStatusEnum11 = " + quotaStatusEnum11);
        Example1StatusEnum quotaStatusEnum12 = MyEnumUtil.toEnumByCode("processing", Example1StatusEnum.class);
        System.out.println("quotaStatusEnum12 = " + quotaStatusEnum12);

        Example2StatusEnum quotaStatusEnum21 = MyEnumUtil.toEnumByCode("processing", Example2StatusEnum.class);
        System.out.println("quotaStatusEnum11 = " + quotaStatusEnum21);
        Example2StatusEnum quotaStatusEnum22 = MyEnumUtil.toEnumByCode("fda", Example2StatusEnum.class);
        System.out.println("quotaStatusEnum12 = " + quotaStatusEnum22);

        Example1StatusEnum enumByDesc11 = MyEnumUtil.toEnumByDesc("新建状态", Example1StatusEnum.class);
        System.out.println("enumByDesc11 = " + enumByDesc11);
        Example1StatusEnum enumByDesc12 = MyEnumUtil.toEnumByDesc("xfdas", Example1StatusEnum.class);
        System.out.println("enumByDesc12 = " + enumByDesc12);
//        Example1StatusEnum enumByDesc13 = MyEnumUtil.toEnumByDesc("新建状态", Example2StatusEnum.class);
//        System.out.println("enumByDesc13 = " + enumByDesc13);
    }

发现如果Example2StatusEnum没有实现BaseDescEnum,连编译都不能通过。为什么上文不建议使用default,这样如果别人不熟悉实现,使用我们的工具类,可以强制让使用该工具类的人员,必须通过BaseDescEnum实现进行重写getDescription,防止忘记重写getDescription,从而获取到错误的description。

正常获取。

至此,优化完成。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Spring Boot启动加载流程自动配置的底层原理(专家解读)

    Spring Boot启动加载流程自动配置的底层原理(专家解读)

    Spring Boot这么少的配置却能实现如此丰富的功能?为何启动一个Spring Boot应用可以变得如此简单便捷?在这个看似平凡的启动过程中,其实隐藏着一套精妙的自动化机制和源码逻辑,本文将带你深入探索 Spring Boot 的启动流程,逐步揭开自动配置的幕后奥秘
    2026-01-01
  • Docker容器Java项目打包与部署全过程

    Docker容器Java项目打包与部署全过程

    Docker是一种容器化技术,可以帮助开发者轻松打包应用程序和依赖,并在任何地方运作它们,这篇文章主要介绍了Docker容器Java项目打包与部署的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-11-11
  • MyBatis 与 Spring 的完美整合方法

    MyBatis 与 Spring 的完美整合方法

    MyBatis 和 Spring 两大框架已经成了 Java 互联网技术主流框架组合,它们经受住了大数据量和大批量请求的考验,在互联网系统中得到了广泛的应用。这篇文章主要介绍了MyBatis 与 Spring 整合,需要的朋友可以参考下
    2018-04-04
  • Spring无法解决循环依赖的五种场景分析

    Spring无法解决循环依赖的五种场景分析

    本文详细分析Spring框架中五类循环依赖问题(构造器注入、原型作用域、@Async、配置类、BeanPostProcessor),提出应急方案如@Lazy、重构设计,并强调通过单一职责、依赖倒置等设计原则避免循环依赖,需要的朋友可以参考下
    2025-05-05
  • 详解AOP与Filter拦截请求打印日志实用例子

    详解AOP与Filter拦截请求打印日志实用例子

    这篇文章主要介绍了详解AOP与Filter拦截请求打印日志实用例子,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • java遍历途中修改数据及删除数据的方法总结

    java遍历途中修改数据及删除数据的方法总结

    在使用java的集合类遍历数据的时候,在某些情况下可能需要对某些数据进行删除,下面这篇文章主要给大家介绍了关于java遍历途中修改数据及删除数据的方法总结,需要的朋友可以参考下
    2023-10-10
  • 浅谈JAVA并发之ReentrantLock

    浅谈JAVA并发之ReentrantLock

    本文主要介绍了基于AQS实现的ReentrantLock(重入锁),感兴趣的同学,可以参考下。
    2021-06-06
  • 解析Tars-Java客户端源码

    解析Tars-Java客户端源码

    Tars是基于名字服务使用Tars协议的高性能RPC开发框架,同时配套一体化的服务治理平台,帮助个人或者企业快速的以微服务的方式构建自己稳定可靠的分布式应用
    2021-06-06
  • 一文解析SpringBoot到底强在哪

    一文解析SpringBoot到底强在哪

    SpringBoot是基于Spring框架的快速开发脚手架,采用约定优于配置的理念,让开发者能够快速创建独立运行、生产级的Spring应用程序,它通过简化配置和自动装配机制,大幅减少了传统Spring应用开发中的样板代码,下面通过本文解析SpringBoot到底强在哪,感兴趣的朋友一起看看吧
    2026-01-01
  • Spring深入刨析声明式事务注解的源码

    Spring深入刨析声明式事务注解的源码

    在spring注解中,使用声明式事务,需要用到两个核心的注解:@Transactional注解和@EnableTransactionManagement注解。将@Transactional注解加在方法上,@EnableTransactionManagement注解加在配置类上
    2022-07-07

最新评论