Java枚举的使用心得

Java枚举

枚举的理解

枚举,的好处就是,在代码输入的时候,可以明确知道可以输入哪些值。而常量,则无法限制。

优点1. 强制性约束

  • 可以让调用者直观且明确的知道,可以传递哪些值
  • 可以约束调用者,必须用指定的Enum。 (看例子)

例子:

public class ConstantTest {
    // 使用常量的好处是简单。这个不用证明大家都明白
    static class OrderConstant {
        // 订单创建
        private static final String ORDER_BUILDER = "01";

        // 订单提交
        private static final String ORDER_COMMIT = "05";

        // 订单取消
        private static final String ORDER_CANCEL = "98";
    }

    enum OrderEnum {
        ORDER_BUILDER,ORDER_COMMIT,ORDER_CANCEL
    }
    @Data
    static class Order {
        private String orderNo;
        private String status;
        private OrderEnum orderEnumStatus;
        private Date createDate;
    }

    public static void main(String[] args) {
        test1();
        test2();

    }

    // 优点1. 强制约束
    public static void test1() {
        Order order = new Order();

//        如果是常量,正常人是这么用的。
        order.setStatus(OrderConstant.ORDER_BUILDER);

        // 准备跑路的程序员可以这么用:可以不通过OrderConstant 进行填写。。有些人可能会瞎几把写代码
        // 这样代码没有约束
        order.setStatus("提桶跑路");

        // 必须强制性天一个Enum类型。 这个就是优点。。
        order.setOrderEnumStatus(OrderEnum.ORDER_BUILDER);

    }

    // 优点2. 可以使用==号,并且不需要做null校验
    public static void test2() {
        Order order = new Order();
        order.setOrderEnumStatus(null);
        if (order.getOrderEnumStatus() == OrderEnum.ORDER_BUILDER) {
            System.out.println("订单创建");
        }
        if (order.getOrderEnumStatus() == null) {
            System.out.println("null 你也敢传");
        }
    }
}

优点2 可以直接使用==

可以直接使用并且,不需要害怕空异常

// 优点2. 可以使用==号,并且不需要做null校验
public static void test2() {
  Order order = new Order();
  order.setOrderEnumStatus(null);
  if (order.getOrderEnumStatus() == OrderEnum.ORDER_BUILDER) {
    System.out.println("订单创建");
  }
  if (order.getOrderEnumStatus() == null) {
    System.out.println("null 你也敢传");
  }
}

优点3 可以用Switch

枚举具体API

枚举格式

修饰符 enum  枚举名称 {
  实例1名称, 实例2名称...;
}

枚举的实质

  • 枚举类实际是 Enum的子类
public abstract class Enum<E extends Enum<E>> 
  extends Object implements Comparable<E>, Serializable
  • Enum 继承了Object 所以,拥有Object 所有方法。

  • Enum可以实现接口。不能继承。

    java 是单继承,所以enum不能再使用extends 。 但是可以实现其他接口。

    /**
     * @author liuqh
     * @version 1.0
     * @date 2022/4/26
     */
    public enum StatusEnum implements NameCodeEnum<String> {
        COMMIT("01", "提交"),TEMP("00", "草稿"),PAUSE("03", "暂停");
    
        private String name;
        private String code;
        StatusEnum(String code, String name) {
            this.code = code;
            this.name = name;
    
        }
        @Override
        public String getName() {
            return name;
        }
    
        @Override
        public String getCode() {
            return code;
        }
    }
    
  • 枚举字面量

    例如:上面的COMMIT 字面量就是COMMIT字符串

  • 枚举特有方法

    // 获得Enum的类对象<E>	getDeclaringClass();
    // 重写了toString 方法。返回枚举常量名称
    String  toString();
    // 通过枚举常量名称, 返回枚举  
    static <T extends Enum<T>> T  valueOf(<T> enumType, String name)
    
    // 返回枚举常量名称, 跟自定义的name没有半毛钱关系
    public final String name();
    // 返回枚举的顺序
    public final int ordinal()
    
  • 枚举构造器

    咱们可以定义自己的构造器,但是枚举内部都会调用Enum的构造器存入ordinal 与 枚举字面量name

    protected Enum(String name,
                   int ordinal)
    唯一的构造函数。 程序员无法调用此构造函数。 它由编译器响应枚举类型声明发出的代码使用。
    参数
    name - - 此枚举常量的名称,它是用于声明它的标识符。
    ordinal - - 这个枚举常数的序数(它在枚举声明中的位置,其中初始常数被分配为零的序数)。
    

通过接口简化枚举

通常业务经常会定义code 与 name, 例如: COMMIT(“01”, “提交”)。 01是code , 提交是name。

经常会有通过code 查找对应的枚举,或者通过name 查找对应的枚举。

问题案例

经常实现:

package com.moveo.dev.enums;

/**
 * @author liuqh
 * @version 1.0
 * @date 2022/4/26
 */
public enum ErrorEnum {
    PASSWD_ERROR("1003", "密码错误"),
    USERNAME_ERROR("1004", "用户名错误"),
    SYSTEM_ERROR("2001", "系统错误")
    ;

    private final String code;
    private final String name;

    private ErrorEnum(String code, String name) {
        this.code = code;
        this.name = name;
    }

    public String getCode() {
        return code;
    }

    public String getName() {
        return name;
    }

    /**
     * 通过code 返回枚举的中文值
     * @author liuqh
     * @param code
     * @return String 空返回null
     * @date 2022/4/26
     **/
    public static String getNameByCode(String code) {
        ErrorEnum[] values = ErrorEnum.values();
        for (ErrorEnum errorEnum : values) {
            if (errorEnum.getCode().equals(code)) {
                return errorEnum.getName();
            }
        }
        // 未找到返回null
        return null;
    }

    /**
     * 通过code 返回枚举。 没找到返回null
     * @author liuqh
     * @param code
     * @return ErrorEnum
     * @date 2022/4/26
     **/
    public static ErrorEnum getEnumByCode(String code) {
        ErrorEnum[] values = ErrorEnum.values();
        for (ErrorEnum errorEnum : values) {
            if (errorEnum.getCode().equals(code)) {
                return errorEnum;
            }
        }
        // 未找到返回null
        return null;
    }
}

问题是每个枚举类型,都需要写一遍getEnumByCode。造成大量的复制粘贴操作

解决案例

思路:枚举虽然不能继承,但是可以通过接口。使用工具类来完成操作。

接口:

/**
 * 这里采用T泛型的原因是,有的枚举类并不需要枚举名且枚举code可能为String 或者Integer
 *
 *
 * @author liuqh
 * @date  2022/4/25
 * @version 1.0
 */
public interface CodeEnum<T> {
    /**
     *获取枚举值
     * @return
     */
    T getCode();
}


/**
 * 带有枚举值以及枚举名称的枚举接口(可以使用{@link EnumUtils} 中的方法)
 *
 * @author liuqh
 * @version 1.0
 * @date 2022/4/25
 */
public interface NameCodeEnum<T> extends CodeEnum<T> {

    /**
     * 获取枚举名称
     *
     * @author liuqh
     * @return String
     * @date 2022/4/25
     **/
    String getName();
}


实现类:

public enum StatusEnum implements NameCodeEnum<String> {
    COMMIT("01", "提交"),TEMP("00", "草稿"),PAUSE("03", "暂停");

    private final String name;
    private final String code;

    StatusEnum(String code, String name) {
        this.code = code;
        this.name = name;

    }
    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getCode() {
        return code;
    }
}

枚举工具类:

package com.moveo.dev.enums;

import org.apache.commons.lang3.StringUtils;

/**
 * @author liuqh
 * @version 1.0
 * @date 2022/4/25
 */
public class EnumUtils {

    /**
     * 判断枚举值是否存在于指定枚举数组中
     *
     * @param enums 枚举数组
     * @param code 枚举code
     * @return 是否存在
     */
    public static <T> boolean isExist(CodeEnum<T>[] enums, T code) {
        if (code == null) {
            return false;
        }
        for (CodeEnum<T> e : enums) {
            if (code.equals(e.getCode())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断枚举值是否存与指定枚举类中
     *
     * @param enumClass 枚举类
     * @param code     枚举code
     * @param <E>       枚举类型
     * @param <V>       值类型
     * @return true:存在
     */
    @SuppressWarnings("unchecked")
    public static <E extends Enum<? extends CodeEnum<V>>, V> boolean isExist(Class<E> enumClass, V code) {
        for (Enum<? extends CodeEnum<V>> e : enumClass.getEnumConstants()) {
            if (((CodeEnum<V>) e).getCode().equals(code)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 根据枚举值获取其对应的名字
     *
     * @param enums 枚举列表
     * @param code 枚举值
     * @return 枚举名称
     */
    public static <T> String getNameByCode(NameCodeEnum<T>[] enums, T code) {
        if (code == null) {
            return null;
        }
        for (NameCodeEnum<T> e : enums) {
            if (code.equals(e.getCode())) {
                return e.getName();
            }
        }
        return null;
    }

    /**
     * 根据枚举名称获取对应的枚举code
     *
     * @param enums 枚举列表
     * @param name  枚举名
     * @return 枚举code
     */
    public static <T> T getCodeByName(NameCodeEnum<T>[] enums, String name) {
        if (StringUtils.isEmpty(name)) {
            return null;
        }
        for (NameCodeEnum<T> e : enums) {
            if (name.equals(e.getName())) {
                return e.getCode();
            }
        }
        return null;
    }

    /**
     * 根据枚举值获取对应的枚举对象
     *
     * @param enums 枚举列表
     * @return 枚举对象
     */
    @SuppressWarnings("unchecked")
    public static <E extends Enum<? extends CodeEnum<V>>, V> E getEnumByCode(E[] enums, V code) {
        for (E e : enums) {
            if (((CodeEnum<V>) e).getCode().equals(code)) {
                return e;
            }
        }
        return null;
    }

    /**
     * 根据枚举值获取对应的枚举对象
     *
     * @param enumClass 枚举class
     * @return 枚举对象
     */
    public static <E extends Enum<? extends CodeEnum<V>>, V> E getEnumByCode(Class<E> enumClass, V Code) {
        return getEnumByCode(enumClass.getEnumConstants(), Code);
    }
    
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值