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
结合场景再看三个关注点
- 比较用
==即可(单例常量)。 - 状态机规则可放 enum 方法,避免散落 if。
valueOf对非法名抛异常,外部输入要先校验。
核心概念与准确模型
1. 本质
- 编译器生成的 final 类,继承
Enum - 常量是 static final 实例
2. 可扩展
- 字段、构造器(private)、方法
- 实现接口
- 常量体覆盖方法(常量特定策略)
3. 常用 API
name()/ordinal()(ordinal 不适合持久化稳定契约)values()/valueOf
边界情况与反直觉行为
- 持久化存 ordinal 后插入新常量会错位——存 name 或稳定 code 字段。
- 枚举单例与反序列化有特殊机制。
- switch 需处理新增常量策略(编译器可帮助)。
常见误区
[!warning] 常见误区:用 ordinal 当数据库主键 顺序变化即数据腐蚀;使用显式 code。
工程实践
- 业务状态用 enum + 明确 code。
- 复杂状态机可用独立表/类,enum 保常量。
- JSON 映射配置枚举格式。
- 权限点等可用 enum 集合。
本节总结
- enum = 类型安全封闭集
- 可承载行为
- 持久化用稳定标识而非 ordinal
自测题
- 为什么枚举常量可以用
==比较? ordinal()的风险是什么?
参考答案
- 每个常量是唯一实例(语言保证的枚举单例语义)。
- 声明顺序变化导致数值变化,不适合作为稳定对外契约。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Enum Types (Oracle Tutorial) | 教程 | enum |
| JLS Enum Classes | 规范 | 枚举类 |