Java中用多维数组构建状态机可行但非主流,适用于状态与事件少、逻辑简单的场景;核心是二维数组查表,行=状态、列=事件、值=目标状态,配合枚举提升类型安全与可读性。

Java 中用多维数组构建状态机不是主流做法,但确实可行——它适合逻辑简单、状态和事件数量固定且较少的场景,比如嵌入式控制、教学示例或小型游戏状态跳转(如 Pong 的菜单↔游戏切换)。它的优势是结构清晰、查表快、无额外依赖;缺点是扩展性差、无法携带行为逻辑、难以支持条件分支或副作用动作。
用二维数组定义状态转移表
核心思路:用 行表示当前状态,列表示触发事件,数组元素存目标状态。状态和事件都用整数索引(或枚举 ordinal 值)映射。
- 定义状态枚举,确保顺序稳定(避免因重构打乱索引):
enum State { MENU, GAME, PAUSE, EXIT } - 定义事件枚举:
enum Event { START_GAME, RETURN_MENU, TOGGLE_PAUSE, QUIT } - 声明转移表(int[状态数][事件数]):
例如int[][] transitions = new int[State.values().length][Event.values().length]; - 初始化表(用 -1 表示非法转移):
transitions[State.MENU.ordinal()][Event.START_GAME.ordinal()] = State.GAME.ordinal();transitions[State.GAME.ordinal()][Event.TOGGLE_PAUSE.ordinal()] = State.PAUSE.ordinal();transitions[State.PAUSE.ordinal()][Event.TOGGLE_PAUSE.ordinal()] = State.GAME.ordinal();
封装状态机类并实现安全转移
避免裸数组操作,封装成可复用的类,加入边界检查与非法转移防护。
- 构造时传入初始状态索引,并缓存状态/事件枚举数组
- 提供
handle(Event e)方法:计算当前状态行 + 事件列 → 查表 → 更新状态 - 若查得值为 -1 或超出状态范围,抛出
IllegalStateException或静默忽略(视业务而定) - 可选:在转移前后调用
onEnter()/onExit()回调(需额外维护状态对象映射)
配合枚举增强可读性与类型安全
纯 int 索引易出错。推荐将数组索引与枚举绑定,对外暴露枚举接口,内部查表。
立即学习“Java免费学习笔记(深入)”;
- 状态机类持有一个
State[] states和Event[] events引用 - 转移方法签名写成:
public void handle(Event event),内部自动转换event.ordinal() - 返回当前状态用
public State currentState(),而非 int - 这样既保留数组性能,又获得编译期检查和语义清晰性
适用边界与替代建议
多维数组方案适合“纯跳转、无动作、少状态”的轻量场景。一旦需求变复杂,就该升级:
- 需要在转移时执行日志、校验、持久化?→ 改用带 action 回调的 Map-based 实现(如
Map<State, Map<Event, Transition>>) - 状态超过 10 个或事件逻辑含条件判断?→ 考虑状态模式(每个 State 是类,含自己的 handle())
- 项目已引入 Spring?→ 直接用 Spring State Machine,支持持久化、事件广播、UML 图生成
- 追求类型安全与编译检查?→ 枚举 + 抽象方法定义合法后继(如知识库中 ONE/TWO/THREE 示例)



















