枚举可通过ordinal()和values()实现上下状态动态获取:prev()用ordinal-1并校验≥0,next()用ordinal+1并校验<values().length,推荐封装为实例方法并缓存values()数组。

Java 枚举类本身是静态的,但可以通过在枚举中定义索引、重写方法或借助 values() 数组实现“上一状态”和“下一状态”的动态获取逻辑。关键在于利用枚举常量的声明顺序(即 ordinal())以及数组边界控制。
利用 ordinal() 和 values() 实现相邻状态
每个枚举实例都有唯一的 ordinal() 值(从 0 开始递增),而 MyEnum.values() 返回按声明顺序排列的数组。据此可安全计算前后状态:
- 获取上一状态:当前
ordinal - 1,需校验是否 ≥ 0 - 获取下一状态:当前
ordinal + 1,需校验是否 <values().length - 推荐封装为实例方法(如
prev()/next()),避免每次手动判断
在枚举中内置 prev() 和 next() 方法
示例代码:
// 定义状态枚举public enum OrderStatus {
DRAFT,
SUBMITTED,
APPROVED,
SHIPPED,
DELIVERED;
// 缓存 values() 提升性能(避免每次调用都新建数组)
private static final OrderStatus[] VALUES = values();
public OrderStatus prev() {
int i = this.ordinal() - 1;
return i >= 0 ? VALUES[i] : null; // 或抛异常/返回自身/循环(按需)
}
public OrderStatus next() {
int i = this.ordinal() + 1;
return i null;
}
}
// 使用
OrderStatus current = OrderStatus.SUBMITTED;
OrderStatus prev = current.prev(); // DRAFT
OrderStatus next = current.next(); // APPROVED
支持循环切换(首尾相连)
若业务允许“DELIVERED 的下一状态是 DRAFT”,可改用取模运算:
立即学习“Java免费学习笔记(深入)”;
-
next()→VALUES[(ordinal() + 1) % VALUES.length] -
prev()→VALUES[(ordinal() - 1 + VALUES.length) % VALUES.length] - 注意:减法需加 length 再取模,避免负数索引
更健壮的设计:用 Map 显式定义流转关系
当状态流转非线性(如 SUBMITTED 可到 APPROVED 或 REJECTED)、或需权限/条件控制时,不建议依赖声明顺序。此时可:
- 用
Map<OrderStatus, OrderStatus>显式配置每个状态的合法后继 - 在枚举构造器中初始化该映射(静态块或私有字段)
- 提供
canTransitionTo(OrderStatus target)等语义化方法
这种方式解耦了逻辑与声明顺序,更适合复杂工作流场景。


















