本质区别在于捕获范围和设计意图:catch (Throwable) 捕获包括 Error 和 Exception 的所有可抛出对象,而 catch (Exception) 仅捕获 Exception 及其子类,排除不可恢复的系统级错误(如 OutOfMemoryError);Java 设计上要求避免捕获 Error,业务代码应优先使用 catch (Exception),仅在全局异常处理器中谨慎使用 catch (Throwable) 并及时终止或告警。

本质区别在于捕获范围和设计意图:catch (Throwable) 捕获一切可抛出对象,包括程序无法恢复的严重错误(Error);catch (Exception) 只捕获程序本意允许处理的异常,排除 Error 类型。
捕获范围不同
Throwable 是 Java 异常体系的根类,有两个直接子类:Exception 和 Error。
- catch (Throwable e) 能捕获所有 Throwable 实例,含 Exception(如 IOException、NullPointerException)、Error(如 OutOfMemoryError、StackOverflowError)及其全部子类。
- catch (Exception e) 仅捕获 Exception 及其子类,完全跳过 Error 及其任何子类。
设计意图与语义不同
Java 明确区分两类问题:
- Error 表示系统级故障,比如 JVM 内存耗尽、类加载失败、线程被强制终止。这些不是程序逻辑缺陷,也无法通过代码修复或恢复,JDK 文档明确指出 “reasonable application should not try to catch”(合理应用不应尝试捕获)。
- Exception 表示可预期、可干预的问题:
- 受检异常(Checked Exception),如 IOException,编译器强制要求处理,代表外部条件导致的、可能重试或降级的失败;
- 非受检异常(Unchecked Exception),如 NullPointerException,反映编程疏漏,应通过修复逻辑而非掩盖来解决。
实际使用建议
绝大多数业务场景下应当使用 catch (Exception),理由如下:
- 避免把不可恢复的 Error 当作普通异常吞掉,防止 JVM 处于不稳定状态却继续运行;
- 不干扰 JVM 对严重错误的默认处理机制(如崩溃前 dump、线程终止);
- 符合 Java 异常分类的设计哲学——让 Exception 承担“可处理”的职责,把 Error 留给运行环境判断;
- 唯一常见例外是顶层全局异常处理器(如 Spring 的 @ControllerAdvice 或自定义 UncaughtExceptionHandler),为记录日志或发送告警而捕获 Throwable,但捕获后通常仍需 re-throw 或调用 System.exit()。
一个直观对比示例
以下代码中:try { throw new OutOfMemoryError("boom"); } catch (Throwable t) { /* 被捕获 */ }try { throw new OutOfMemoryError("boom"); } catch (Exception e) { /* 完全不执行,编译通过但无效果 */ }


















