try-catch-finally与断言是分工明确的协作机制:前者处理可预期、需恢复的运行时问题,后者专用于开发阶段验证内部假设、暴露逻辑缺陷;断言默认关闭,生产环境禁用,不可替代异常处理。

try-catch-finally 和断言(assert)不是替代关系,而是分工明确的协作机制:前者处理**可预期、需恢复的运行时问题**,后者用于**开发阶段验证假设、暴露逻辑缺陷**。混用或误用反而会掩盖真实问题,甚至影响生产环境稳定性。
断言只在开发调试阶段启用
Java 的 assert 默认是关闭的,必须通过 JVM 参数 -ea(enable assertions)显式开启。生产环境通常禁用断言,因为它不承担错误恢复职责,也不该被用来处理用户输入、I/O失败等外部不确定性因素。
- 断言适合检查“绝不该发生”的内部状态,比如:
— 方法参数在私有工具类中已被预校验,后续逻辑默认其非 null;
— 循环退出时某个计数器理论上必须等于预期值;
— switch 分支已覆盖全部枚举项,default 分支仅作兜底断言。 - 错误用法示例:
assert new File("config.txt").exists() : "配置文件丢失";
这属于 I/O 类受查异常场景,应由 try-catch 处理,而非断言。
try-catch-finally 负责资源与流程兜底
当操作涉及外部资源(文件、网络、数据库连接)或用户不可控输入时,必须依赖 try-catch-finally 或更现代的 try-with-resources 进行结构化错误应对和资源释放。
- catch 块应按异常具体类型分层捕获,优先处理业务相关异常(如
IllegalArgumentException),再捕获通用异常(如IOException),避免用catch (Exception e)一锅端。 - finally 块专注清理,不建议在里面写 return 或修改返回值——它会覆盖 try/catch 中的返回结果,造成逻辑混乱。
- JDK 7+ 推荐优先使用 try-with-resources:自动调用
close(),且能保留原始异常(close 异常作为 suppressed exception 附加),比手写 finally 更安全可靠。
二者协同的典型场景
断言可嵌入 try-catch 的逻辑路径中,用于确认异常处理后的内部状态是否符合预期,但仅限开发验证。
- 例如,在 catch 块中重试失败操作后,用断言确认重试次数未超限:
retryCount++; assert retryCount - 又如,finally 关闭资源后,可用断言辅助调试(仅调试期):
resource.close(); assert !resource.isOpen() : "资源关闭失败";
注意:该断言不能替代对 close() 抛出异常的捕获(如 IOException),因为关闭本身可能失败。
避免常见陷阱
把断言当成异常处理,或在生产代码中依赖断言做流程控制,都会带来隐患。
- 断言失败抛出的是
AssertionError(继承自Error),不属于 Exception 体系,无法被普通 catch 捕获,也不该被程序试图“恢复”。 - 不要在 public 方法的前置条件校验中依赖断言——用户传入非法参数是常态,应抛出
IllegalArgumentException并由调用方处理。 - 断言表达式里避免有副作用(如修改变量、触发 I/O),因为上线后断言关闭,这些操作将消失,导致行为不一致。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











