java异常处理高分关键在于精准区分异常类型与责任边界:受检异常必须处理或声明,非受检异常应修复逻辑而非捕获,error不捕获;优先用try-with-resources防泄漏,捕获具体异常而非exception,自定义业务异常增强语义,日志记录需脱敏且带业务上下文。

想在Java异常处理上拿高分,关键不是堆砌语法,而是理解“什么时候该捕、什么时候该抛、什么时候该换、什么时候该记”。高分答案往往体现对异常语义的尊重和对系统责任边界的清醒认知。
精准区分异常类型,不混用
考试或面试中,混淆Checked与Unchecked异常是典型扣分点。比如文件读取必须声明IOException(受检),而NullPointerException属于运行时异常,不应强制try-catch——它暴露的是逻辑缺陷,该修代码,不该兜底。
- 受检异常(如
SQLException、ClassNotFoundException):代表外部不确定性(IO、网络、配置),必须显式处理或向上声明 - 非受检异常(
RuntimeException子类):代表程序逻辑错误,应通过校验、断言提前规避,而非靠catch掩盖 - Error及其子类(如
OutOfMemoryError):不捕获、不重试、不记录——JVM已失稳,强行处理反而干扰诊断
try-with-resources替代手动finally
资源泄漏是高频失分项。用传统try-finally关流,容易漏写或顺序错;用try-with-resources则由编译器保障自动关闭,且支持多资源声明:
try (FileInputStream fis = new FileInputStream("a.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(fis))) {
// 业务逻辑
} catch (IOException e) {
// 统一处理IO异常
}
注意:资源类必须实现AutoCloseable接口,且关闭异常会被抑制(可通过getSuppressed()获取),避免掩盖主异常。
捕获具体异常,拒绝Exception万能兜底
写catch(Exception e)看似省事,实则丢弃关键上下文,是反模式。高分做法是按实际可能抛出的最小异常类型捕获:
- 解析数字用
NumberFormatException,不是IllegalArgumentException - 数组访问用
ArrayIndexOutOfBoundsException,不是RuntimeException - 多个异常分别处理:
catch (IOException | SQLException e)(Java 7+多异常捕获)
这样既便于日志分类统计,也方便调用方针对性重试或降级。
自定义异常带业务语义
当标准异常无法表达领域意图时,高分答案会设计语义清晰的自定义异常。例如电商场景:
-
InsufficientStockException比RuntimeException更能说明问题本质 - 继承
RuntimeException(非受检),因库存不足属业务规则违反,非系统故障 - 构造器传入订单ID、商品SKU等上下文字段,便于追踪定位
不建议为所有方法都加throws声明——只在异常需由调用方决策时(如重试、告警、补偿)才暴露。
日志记录不打印堆栈,除非必要
生产环境滥用e.printStackTrace()是硬伤。高分实践是:
- 仅在调试阶段用
printStackTrace()快速定位 - 生产环境用SLF4J等日志框架,记录
logger.error("下单失败,订单号:{},原因:{}", orderId, e.getMessage(), e) - 敏感信息(密码、密钥、用户身份证)绝不出现在日志中
异常消息本身应描述“发生了什么”,而不是“怎么发生的”——后者由堆栈提供,前者由业务开发者定义。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











