可以直接用 throw 关键字重新抛出 catch 中捕获的异常对象,无需新建或包装,原异常的类型、消息、堆栈信息都会完整保留;直接 throw e; 能原样向上抛出,堆栈跟踪从原始抛出点开始,适合仅做日志或清理后交由上层处理的场景。

可以直接用 throw 关键字重新抛出 catch 中捕获的异常对象,无需新建或包装,原异常的类型、消息、堆栈信息都会完整保留。
直接 throw 原异常对象
在 catch 块中,直接写 throw e;(假设异常变量名为 e),就能将当前捕获的异常原样向上抛出:
- 不改变异常类型(比如捕获的是
NullPointerException,抛出的仍是它) - 堆栈跟踪从原始抛出点开始,未被截断(即
printStackTrace()显示最初出错位置) - 适合“我只做日志或清理,不处理逻辑,让上层决定怎么应对”的场景
注意变量名和作用域
catch 参数是局部变量,名字可自定义,但必须是已捕获的异常引用:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
-
catch (IOException e) { throw e; }✅ 正确 -
catch (Exception e) { throw new RuntimeException(e); }❌ 这是包装,不是重新抛出原异常 - 不能在 catch 外部访问
e,也不能在 try 或 finally 里直接 throw 它
和 throw new Xxx() 的区别
重新抛出原异常 ≠ 创建新异常:
立即学习“Java免费学习笔记(深入)”;
-
throw e;:堆栈起点不变,调用链清晰 -
throw new RuntimeException(e);:新异常包裹旧异常,堆栈起点变成当前行,需用getCause()查原始错误 - 若只想补充上下文又保留原始堆栈,可用
initCause()或带 cause 的构造器,但仍是新建对象
常见误用:在 finally 里 throw
避免在 finally 块中无条件 throw 异常,否则会覆盖 try/catch 中的异常:
- 如果 try 抛了异常 A,catch 捕获后执行
throw e;,但 finally 又throw new B();→ 最终抛出的是 B,A 被吞掉 - finally 中抛异常应有明确条件(如资源关闭失败且主异常为 null),否则慎用

















