美文网首页
Java枚举

Java枚举

作者: yueming15899 | 来源:发表于2020-05-26 16:46 被阅读0次

    简介

    枚举类型是一种使用一组预定义的常量表示的一种特殊数据类型。enum关键字在 java5 中引入,所有的枚举类默认都集成自java.lang.Enum类。

    //基本写法
    public enum Day {
        SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
        THURSDAY, FRIDAY, SATURDAY 
    }
    

    枚举与常量比较

    • 优点
      1. 可读性更高
      2. 编译时检查减少代码错误(相对于基本数据类型的常量)
      3. 表现力更强(相对于基本数据类型的常量)
      4. 使用 == 对枚举进行比较提供编译时和运行时的安全性
    • 缺点
      1. 增加类的数目
      2. 数据转换麻烦
    public class Date {
    
        private Day day;
    
        public static void main(String[] args) {
            Date today = new Date();
            //可能会出NPE
            if (today.getDay().equals(Day.FRIDAY)) {
                //todo
            }
            //使用==保证运行时安全
            if (today.getDay() == Day.FRIDAY) {
                //todo
            }
           //比较会得到true
            if (today.getDay().equals(Color.FRIDAY)) {
                //todo
            }
            //编译报错保证编译检查安全
            //if (today.getDay() ==  Color.FRIDAY) {
                //todo
            //}
        }
    
        public Day getDay() {
            return day;
        }
    
        public void setDay(Day day) {
            this.day = day;
        }
    }
    enum Color {
        RED,GREEN,FRIDAY
    }
    

    使用场景与实例

    1. 在switch中使用
        public static boolean isWeekend(Day day) {
            switch (day) {
                case SATURDAY:
                case SUNDAY:
                    return true;
                default:
                    return false;
            }
        }
    
    1. 枚举类型增加属性和方法
    public enum RepayMethod {
        
        BULLET_REPAYMENT(1, "一次性还款"),
        INTEREST(2, "先息后本"),
        EQUAL_INSTALLMENT(4, "等额本息"),
        EQUAL_PRINCIPAL(8, "等额本金");
    
        private Integer code;
        private String msg;
    
        private RepayMethod(Integer type, String msg) {
            this.code = type;
            this.msg = msg;
        }
    
        public Integer getCode() {
            return code;
        }
    
        public void setCode(Integer code) {
            this.code = code;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
    }
    
    1. java8 lambda使用枚举
    public class Loan {
    
        private Long id;
    
        private RepayMethod repayMethod;
    
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public RepayMethod getRepayMethod() {
            return repayMethod;
        }
    
        public void setRepayMethod(RepayMethod repayMethod) {
            this.repayMethod = repayMethod;
        }
    
    
    
        public static List<Loan> groupByRepayMethod(List<Loan> list, RepayMethod repayMethod) {
            return list.stream().filter(loan -> repayMethod == loan.repayMethod).collect(Collectors.toList());
        }
    
    
    }
    
    1. EnumSet
      EnumSet 是一种专门为枚举类型所设计的 Set 类型。与HashSet相比,由于使用了内部位向量表示,因此它是特定 Enum 常量集的非常有效且紧凑的表示形式。EnumSet 是抽象类,其有两个实现:RegularEnumSet (小于等于64个元素使用)、JumboEnumSet,选择哪一个取决于实例化时枚举中常量的数量。使用EnumSet的of方法来构建EnumSet。
        private  static EnumSet<RepayMethod> MULTIPLE_PERIOD_REPAY_METHOD = EnumSet.of(INTEREST,EQUAL_INSTALLMENT,EQUAL_PRINCIPAL);
        
        public static boolean isMultiplePeriod(RepayMethod repayMethod) {
            return MULTIPLE_PERIOD_REPAY_METHOD.contains(repayMethod);
        }
    
    1. EnumMap
      EnumMap是一个专门化的映射实现,用于将枚举常量用作键。与对应的 HashMap 相比,它是一个高效紧凑的实现,并且在内部表示为一个数组
        public static EnumMap<RepayMethod, List<Loan>> groupByRepayMethod(List<Loan> list) {
            EnumMap<RepayMethod, List<Loan>> map = new EnumMap(RepayMethod.class);
            for (Loan loan : list) {
                if (map.containsKey(loan.getRepayMethod())) {
                    map.get(loan.getRepayMethod()).add(loan);
                } else {
                    List<Loan> groupList = new ArrayList<>();
                    groupList.add(loan);
                    map.put(loan.getRepayMethod(),groupList);
                }
            }
            return map;
        }
    
    1. 使用枚举实现单例模式
    public enum Singleton {
        INSTANCE;
    
        public void service() {
            //todo
        }
    }
    
    1. 使用枚举实现策略模式(适用于处理逻辑较为简单的策略模式)
    public enum RepayTypeStrategy {
    
        BULLET_REPAYMENT {
            @Override
            public void createLoanRepay(Loan loan) {
                //todo
            }
        },
        INTEREST {
            @Override
            public void createLoanRepay(Loan loan) {
              //todo
            }
        };
    
        public abstract void createLoanRepay(Loan loan);
        
    }
    

    相关原理

    使用javap对编译好的枚举类字节码进行反编译得到如下信息,可以发现其继承自java.lang.Enum,其实现还是静态常量的方式实现的,EnumSet和EnumMap利用到了Enum的ordinal字段,具体详情可以查看源码。

    Compiled from "RepayMethod.java"
    public final class com.yueyang.se.enumeration.RepayMethod extends java.lang.Enum<com.yueyang.se.enumeration.RepayMethod> {
      public static final com.yueyang.se.enumeration.RepayMethod BULLET_REPAYMENT;
      public static final com.yueyang.se.enumeration.RepayMethod INTEREST;
      public static final com.yueyang.se.enumeration.RepayMethod EQUAL_INSTALLMENT;
      public static final com.yueyang.se.enumeration.RepayMethod EQUAL_PRINCIPAL;
      public static com.yueyang.se.enumeration.RepayMethod[] values();
      public static com.yueyang.se.enumeration.RepayMethod valueOf(java.lang.String);
      public java.lang.Integer getCode();
      public void setCode(java.lang.Integer);
      public java.lang.String getMsg();
      public void setMsg(java.lang.String);
      public static boolean isMultiplePeriod(com.yueyang.se.enumeration.RepayMethod);
      static {};
    }
    
    

    相关文章

      网友评论

          本文标题:Java枚举

          本文链接:https://www.haomeiwen.com/subject/fuyuahtx.html