IllegalStateException的核心价值在于用明确语义拦截非法状态跃迁:通过入口状态校验、方法契约绑定、配套查询方法及并发原子化控制,防止生命周期混乱引发的隐式错误。

IllegalStateException 的核心价值,不在于“报错”,而在于用明确的语义拦截那些本不该发生的流程跳跃——尤其是对象生命周期中状态跃迁失控的情况。
用状态校验代替隐式失败
对象生命周期通常有清晰阶段:未初始化 → 初始化完成 → 正在运行 → 已停止 → 已销毁。若跳过中间环节(比如直接从“未初始化”调用 stop(),或对“已销毁”对象再次 start()),程序不会崩溃,但可能静默忽略、数据错乱或资源泄漏。此时主动抛出 IllegalStateException,相当于给非法跃迁装上红灯:
- 在每个关键方法入口检查当前状态变量(如 isInitialized、isRunning、isClosed)
- 不满足前置条件时,立刻 throw new IllegalStateException("Expected state: INITIALIZED, but got: " + currentState)
- 避免靠返回值或布尔标志“委婉提示”,那容易被调用方忽略
绑定状态变更与方法契约
每个公开方法都应隐含一个状态契约。例如:
- start() 要求:!isRunning && isInitialized
- pause() 要求:isRunning && !isPaused
- close() 要求:!isClosed(且无论是否运行中都允许关闭)
把契约写进 Javadoc,并在实现中强制校验。这样,非法调用不是“执行失败”,而是“契约违约”,异常信息能直接暴露哪条规则被绕过了。
配合 isXxx() 状态查询方法预防调用
仅靠抛异常不够友好。提供配套的状态判断方法,让调用方能主动规避:
- public boolean canStart() { return !isRunning && isInitialized; }
- public boolean isClosed() { return isClosed; }
- 调用方可用 if (task.canStart()) task.start(); 而非盲目 try-catch
- 这种组合既提升健壮性,又不牺牲 API 易用性
多线程下状态跃迁需原子化
生命周期状态变更本身可能被并发打断。例如两个线程同时调用 start(),可能都通过了 if (!isRunning) 检查,然后都设为 true —— 导致重复启动。
- 用 volatile + CAS(如 AtomicBoolean.compareAndSet)保证状态更新原子性
- 或用 synchronized 块包裹整个状态校验+变更逻辑
- 否则即使抛了 IllegalStateException,也可能是竞态导致的“误报”,掩盖真正问题

















