Java枚举

简介

枚举类型是一种使用一组预定义的常量表示的一种特殊数据类型。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 groupByRepayMethod(List 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 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> groupByRepayMethod(List list) {
        EnumMap> map = new EnumMap(RepayMethod.class);
        for (Loan loan : list) {
            if (map.containsKey(loan.getRepayMethod())) {
                map.get(loan.getRepayMethod()).add(loan);
            } else {
                List 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 {
  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枚举)