enum 本质是继承 java.lang.Enum 的 final 类,每个常量是它的一个静态单例实例:
// 编译器眼中,enum WAIT_PAY, PAID 大致等价于:
public final class OrderStatus extends Enum<OrderStatus> {
public static final OrderStatus WAIT_PAY = new OrderStatus("WAIT_PAY", 0);
public static final OrderStatus PAID = new OrderStatus("PAID", 1);
// name 与 ordinal 由父类字段持有
}
跟着做
步骤 1:定义带行为的订单状态 enum
新建 EnumDemo.java,完整可运行:
public class EnumDemo {
public enum OrderStatus {
WAIT_PAY(10, "待支付"),
PAID(20, "已支付"),
SHIPPED(30, "已发货"),
REFUNDED(40, "已退款");
private final int code; // 存数据库的显式编码
private final String desc; // 给前端展示的文案
OrderStatus(int code, String desc) {
this.code = code;
this.desc = desc;
}
public int code() { return code; }
public String desc() { return desc; }
/** 是否已付过钱:发货、退款都建立在已支付之上 */
public boolean paid() {
return this == PAID || this == SHIPPED || this == REFUNDED;
}
/** 由数据库编码反查枚举;查不到直接抛异常,绝不让脏数据溜过去 */
public static OrderStatus of(int code) {
for (OrderStatus s : values()) {
if (s.code == code) return s;
}
throw new IllegalArgumentException("未知订单状态编码: " + code);
}
}
public static void main(String[] args) {
OrderStatus s = OrderStatus.of(20);
System.out.println(s + " -> " + s.desc() + ", 已付款=" + s.paid());
System.out.println(s == OrderStatus.PAID); // true,枚举比较用 ==
System.out.println(s.equals(OrderStatus.PAID)); // true,但没必要
try {
OrderStatus.of(99);
} catch (IllegalArgumentException e) {
System.out.println("拦截脏数据: " + e.getMessage());
}
}
}
运行:java EnumDemo.java。
步骤 2:加入 switch 表达式,验证强制穷尽
在 EnumDemo 里加入以下方法,并把 main 换成调用它的版本:
static String nextAction(OrderStatus status) {
return switch (status) {
case WAIT_PAY -> "发送催付通知";
case PAID -> "通知仓库发货";
case SHIPPED -> "等待用户签收";
case REFUNDED -> "关闭工单";
};
}
public static void main(String[] args) {
for (OrderStatus s : OrderStatus.values()) {
System.out.println(s + " -> " + nextAction(s));
}
}
然后注释掉 case SHIPPED 一行再编译——直接失败,提示 switch 表达式未覆盖所有输入值。这就是「漏分支在编译期暴露」,if-else 链永远做不到。