这篇文章由 JavaGuide 翻译,公众号: JavaGuide,原文地址:https://www.baeldung.com/a-guide-to-java-enums 。
1.基本使用
定义一个披萨订单的状态枚举【接单-准备好-已交付】(参考美团外卖)
public enum PizzaStatus {
ORDERED,
READY,
DELIVERED;
}
public int getDeliveryTimeInDays() {
//status为你输入的状态
switch (status) {
case ORDERED:
return 5;
case READY:
return 2;
case DELIVERED:
return 0;
}
return 0;
}
2.自定义枚举方法
定义
public class Pizza {
private PizzaStatus status;
//用于判断披萨是否准备好了
public boolean isDeliverable() {
//setStatus(Pizza.PizzaStatus.READY)
//通过getStatus获取status与PizzaStatus.READY比较
return getStatus() == PizzaStatus.READY;
}
public PizzaStatus getStatus() {
return status;
}
public void setStatus(PizzaStatus status) {
this.status = status;
}
public enum PizzaStatus {
//ORDERED 已接单 READY已准备好 DELIVERED已交付
ORDERED,
READY,
DELIVERED;
}
}
使用
public void givenPizaOrder_whenReady_thenDeliverable() {
Pizza testPz = new Pizza();
//新建一个披萨订单,为其设置订单状态
testPz.setStatus(Pizza.PizzaStatus.READY);
//判断披萨是否准备好了
System.out.println(testPz.isDeliverable());
}
为什么要是有==而不是equals()?
1.枚举类型确保JVM中仅存在一个常量实例,因此我们可以安全地使用 == 运算符比较两个变量
2.== 运算符可提供编译时和运行时的安全性。
如果两个值均为null 都不会引发 NullPointerException。相反,如果使用equals方法,将抛出 NullPointerException:
Pizza.PizzaStatus pizza = null;
System.out.println(pizza.equals(Pizza.PizzaStatus.DELIVERED));//空指针异常
System.out.println(pizza == Pizza.PizzaStatus.DELIVERED);//正常运行
两个不同枚举类型进行比较
if (Pizza.PizzaStatus.DELIVERED.equals(TestColor.GREEN)); // 编译正常
if (Pizza.PizzaStatus.DELIVERED == TestColor.GREEN); // 编译失败,类型不匹配
3.枚举类型的属性、方法和构造器
public class Pizza {
private PizzaStatus status;
public PizzaStatus getStatus() {
return status;
}
public void setStatus(PizzaStatus status) {
this.status = status;
}
public boolean isDeliverable() {
return this.status.isReady();
}
/*
testPz.printTimeToDeliver();
输出:Time to delivery is 2
可见,在testPz.setStatus(Pizza.PizzaStatus.READY)时调用了PizzaStatus(int timeToDelivery)
将 READY(2)赋值给了timeToDelivery
*/
public void printTimeToDeliver() {
System.out.println("Time to delivery is " +
this.getStatus().getTimeToDelivery());
}
public enum PizzaStatus {
//注:枚举写在最前面,否则编译出错
//ORDERED 已接单 READY已准备好 DELIVERED已交付
//通过括号赋值,而且必须带有一个参构造器和一个属性跟方法,否则编译出错
//赋值必须都赋值或都不赋值,不能一部分赋值一部分不赋值;如果不赋值则不能写构造器,赋值编译也出错
//如果setStatus为此状态,则调用isOrdered时调用的是被覆盖的(1),都在就是初始的(0)
ORDERED(5) {
@Override
//1
public boolean isOrdered() {
return true;
}
},
READY(2) {
@Override
public boolean isReady() {
return true;
}
},
DELIVERED(0) {
@Override
public boolean isDelivered() {
return true;
}
};
private int timeToDelivery;
PizzaStatus(int timeToDelivery) {
this.timeToDelivery = timeToDelivery;
}
//0
public boolean isOrdered() {
return false;
}
public boolean isReady() {
return false;
}
public boolean isDelivered() {
return false;
}
public int getTimeToDelivery() {
return timeToDelivery;
}
}
}
4.EnumSet and EnumMap
Java中的java.util.EnumSet.of(E ele1,E ele2,E ele3,…)方法用于创建一个枚举集,该枚举集最初在参数中包含指定的元素。
如果同时添加多个项目,则在添加新元素时将元素向下推到集合中。
EnumSet.of(1,2,3,4,5,6)//1,2,3,4,5,6
在不同的时间或迭代添加不同的元素时,将替换旧元素(不是追加是覆盖)
第一次.EnumSet.of(1,2,3)//1,2,3
第二次.EnumSet.of(2,3,4)//2,3,4
第三次.EnumSet.of(,4,5,6)//4,5,6
//创建一个用于储存未送达披萨的EnumSet集合
private static EnumSet<PizzaStatus> undeliveredPizzaStatuses =
EnumSet.of(PizzaStatus.ORDERED, PizzaStatus.READY);
/*
输入和输出的List<Pizza>内容不一样
(s)就是Pizza,list遍历
采用流过滤input中的元素
undeliveredPizzaStatuses.contains();检查s是否在EnumSet集合内
.collect(Collectors.toList());将流转化为list
*/
public static List<Pizza> getAllUndeliveredPizzas(List<Pizza> input) {
return input.stream().filter(
(s) -> undeliveredPizzaStatuses.contains(s.getStatus()))
.collect(Collectors.toList());
}
//意思就是把这单变成已送达,饿汉单例模式
public void deliver() {
//如果是准备好的
if (isDeliverable()) {
//管理系统-实例-交付策略-送达
PizzaDeliverySystemConfiguration.getInstance().getDeliveryStrategy()
.deliver(this);
this.setStatus(PizzaStatus.DELIVERED);
}
}