• 【工具类】比较优雅的在工具类中,用泛型方法获取枚举的值


    痛点

    在代码中,经常用到枚举,也经常用到枚举获取code,获取type,通常我们写的代码如下:

     public  enum Status{
        /**
         *
         */
        YES(1,"是"),
        NO(2,"否")
    
        ;
        private int code;
        private String msg;
    
        Status(int code, String msg) {
          this.code = code;
          this.msg = msg;
        }
    
    
        public int getCode() {
          return this.code;
        }
    
    
        public String getMsg() {
          return this.msg;
        }
    
        public static Optional<Status> of(int code) {
          for (Status value : values()) {
             if (Objects.equals(value.getCode(),code)){
              return Optional.of(value);
            }
          }
          return Optional.empty();
        }
    
    
      }
    
    • 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

    要根据某个code,得到枚举以及对应的msg,调用of()方法。但是这样的话每个枚举都得写一边,代码行数还不少。不简洁

    一开始的优化,就是写了个接口如下:

    public interface IEntityEnum {
    
     public int getCode();
    
     public String getMsg();
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    然后枚举实现这个接口,相当于一个标准能保证枚举类都能有这样的of方法可以用。但是实际问题还是没解决,代码在每个枚举都要复制。

    解决

    其实这个也不难想,把这些of方法通通抽取出去在一个工具类中,采用泛型来匹配各种枚举类,但是问题在于,怎么调用values方法呢?怎么告诉编译器我这个方法需要的是一个枚举,我要调用它的values方法,毕竟其他类又没这个静态方法。直到我无意发现了getEnumConstants方法,它是Object类里的。
    它的介绍:

    an array containing the values comprising the enum class represented by this Class object in the order they’re declared, or null if this Class object does not represent an enum type

    一个数组,其中包含组成此 Class 对象表示的枚举类的值,按声明的顺序排列;如果此 Class 对象不表示枚举类型,则为 null

    因此工具类就好写了:

    
    import cn.hutool.core.util.StrUtil;
    import java.util.Optional;
    
    /**
     * EnumsUtil
     *
     * @author zgd
     * @date 2022/8/9 17:44
     */
    public class EnumsUtil {
    
        public static <T extends IEntityEnum> Optional<T> of(int code, Class<T>  cla) {
            T[] enums = cla.getEnumConstants();
            for (T value : enums) {
                if (code == value.getCode()){
                    return Optional.of(value);
                }
            }
            return Optional.empty();
        }
    
    
    
        public static <T extends IEntityEnum> String ofMsg(int code, Class<T>  cla) {
            Optional<T> of = of(code,cla);
            return of.isPresent() ? of.get().getMsg() : "";
        }
    
        public static <T extends IEntityEnum> Integer ofCode(String msg, Class<T>  cla) {
            if (StrUtil.isEmpty(msg)){
                return null;
            }
            T[] enums = cla.getEnumConstants();
            for (T value : enums) {
                if (msg.equals(value.getMsg())){
                    return value.getCode();
                }
            }
            return null;
        }
    /**
    * 可以试下效果
    */
        public static void main(String[] args) {
            System.out.println(EnumsUtil.ofMsg(1, SourceEnum.class));
            System.out.println(EnumsUtil.ofMsg(2, SourceEnum.class));
        }
    }
    
    
    
    • 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
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    优化更灵活的泛型

    用了一天后发现一个问题, 接口IEntityEnum写死了int code和String msg, 那如果有时候code我们需要String类型,这个场景也很常见.
    因此再往上包装一层

    • 增加一个接口
    
    /**
     * IEnum
     *
     * @author zgd
     * @date 2022/8/10 18:09
     */
    public interface IEnum<T,E> {
    
        public T getCode();
    
        public E getMsg();
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 继承这个接口,这个用的比较多,作为一个默认的子接口
    public interface IEntityEnum extends IEnum<Integer,String> {
    
     public Integer getCode();
    
     public String getMsg();
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    
    import cn.hutool.core.util.StrUtil;
    
    import java.util.Optional;
    
    /**
     * EnumsUtil
     *
     * @author zgd
     * @date 2022/8/9 17:44
     */
    public class EnumsUtil {
    
        public static  <E,V,T extends IEnum<E,V>>  Optional<T> of(E code, Class<T>  cla) {
            T[] enums = cla.getEnumConstants();
            for (T value : enums) {
                if (code == value.getCode()){
                    return Optional.of(value);
                }
            }
            return Optional.empty();
        }
    
    
    
        public static <E,V,T extends IEnum<E,V>> V ofMsg(E code, Class<T>  cla) {
            Optional<T> of = of(code,cla);
            return of.map(IEnum::getMsg).orElse(null);
        }
    
        public static <E,V,T extends IEnum<E,V>> E ofCode(String msg, Class<T>  cla) {
            if (StrUtil.isEmpty(msg)){
                return null;
            }
            T[] enums = cla.getEnumConstants();
            for (T value : enums) {
                if (msg.equals(value.getMsg())){
                    return value.getCode();
                }
            }
            return null;
        }
    
        public static void main(String[] args) {
            System.out.println(EnumsUtil.ofMsg("YES", TypeEnum.class));
        }
    }
    
    • 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
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 如果我们需要一个code是String类型的,不实现IEntityEnum,直接实现它的父接口
      /**
         * TypeEnum
         *
         * @author zgd
         * @date 2022/8/10 18:41
         */
        public enum TypeEnum implements IEnum<String,String> {
    
            /**
             *
            */
            YES("YES","是"),
            NO("NO","否"),
    
            ;
    
            private String code;
            private String msg;
    
            TypeEnum(String code, String msg) {
                this.code = code;
                this.msg = msg;
            }
    
            @Override
            public String getCode() {
                return this.code;
            }
    
            @Override
            public String getMsg() {
                return this.msg;
            }
        }
    
    • 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
  • 相关阅读:
    【监督学习】套索回归与岭回归(含代码)
    C-数据结构-树状存储基本概念
    Spring Cloud Alibaba 容器化部署最佳实践 | 本地部署版本 | Rocketmq组件安装
    Vue 重要内置关系:VueComponent.prototype.__proto__ === Vue.prototype及原型链图解
    开源校园服务小程序源码 校园综合服务小程序源码 包含快递代取 打印服务 校园跑腿【带详细部署教程】
    python自动化测试中装饰器@ddt和@data源码解析
    Pandas数据分析16——pandas生成虚拟变量,因子化,列表爆炸等操作
    vue3 + vue-cli3/4配置svg文件的全局使用
    记一次MySQL安装过程中遇到的问题
    Qt加Opencv实现 梯度矫正 功能
  • 原文地址:https://blog.csdn.net/zzzgd_666/article/details/126253067