Java 枚举

enum 如何表达封闭常量集:类型安全、方法与字段、switch 与序列化边界。

#type / concept #status / growing #tech / dev #resource / java

[!info] 关联笔记

Java 枚举

这个概念为什么出现

订单状态、支付渠道、权限级别是封闭且有限的集合。用 int/String 魔法值易拼错;enum 提供类型安全的常量集,并可挂行为。

[!abstract] 一句话理解 enum 是类型安全的封闭常量集合,每个常量是单例实例,可拥有字段与方法,并与 switch 良好配合。

最小可运行示例

场景:订单状态允许的合法迁移

enum OrderStatus {
    CREATED, PAID, SHIPPED, CANCELLED;

    boolean canTransitTo(OrderStatus next) {
        return switch (this) {
            case CREATED -> next == PAID || next == CANCELLED;
            case PAID -> next == SHIPPED || next == CANCELLED;
            case SHIPPED, CANCELLED -> false;
        };
    }
}

public class OrderStatusDemo {
    public static void main(String[] args) {
        System.out.println(OrderStatus.CREATED.canTransitTo(OrderStatus.PAID));
        System.out.println(OrderStatus.SHIPPED.canTransitTo(OrderStatus.PAID));
        System.out.println(OrderStatus.PAID.name());
    }
}

建议运行:

javac OrderStatusDemo.java && java OrderStatusDemo

期望输出:

true
false
PAID

结合场景再看三个关注点

  1. 比较用 == 即可(单例常量)。
  2. 状态机规则可放 enum 方法,避免散落 if。
  3. valueOf 对非法名抛异常,外部输入要先校验。

核心概念与准确模型

1. 本质

  • 编译器生成的 final 类,继承 Enum
  • 常量是 static final 实例

2. 可扩展

  • 字段、构造器(private)、方法
  • 实现接口
  • 常量体覆盖方法(常量特定策略)

3. 常用 API

  • name()/ordinal()(ordinal 不适合持久化稳定契约)
  • values()/valueOf

边界情况与反直觉行为

  1. 持久化存 ordinal 后插入新常量会错位——存 name 或稳定 code 字段。
  2. 枚举单例与反序列化有特殊机制。
  3. switch 需处理新增常量策略(编译器可帮助)。

常见误区

[!warning] 常见误区:用 ordinal 当数据库主键 顺序变化即数据腐蚀;使用显式 code。

工程实践

  1. 业务状态用 enum + 明确 code。
  2. 复杂状态机可用独立表/类,enum 保常量。
  3. JSON 映射配置枚举格式。
  4. 权限点等可用 enum 集合。

本节总结

  • enum = 类型安全封闭集
  • 可承载行为
  • 持久化用稳定标识而非 ordinal

自测题

  1. 为什么枚举常量可以用 == 比较?
  2. ordinal() 的风险是什么?
参考答案
  1. 每个常量是唯一实例(语言保证的枚举单例语义)。
  2. 声明顺序变化导致数值变化,不适合作为稳定对外契约。

延伸阅读与资料来源

资料类型支撑内容
Enum Types (Oracle Tutorial)教程enum
JLS Enum Classes规范枚举类
创建于 2026/7/15 更新于 2026/7/15