最合理的做法是重新抛出或包装异常而非静默吞掉;应明确异常责任归属,由更有上下文的层级处理;推荐用自定义业务异常包装原始异常并传入cause;捕获时需记录关键上下文日志,避免敏感信息泄露;finally中仅做资源清理,禁用return或throw干扰主流程。

当catch块无法真正解决异常时,最合理的做法是重新抛出异常或包装后抛出,而不是静默吞掉或用空catch草率处理。
明确异常责任归属
不是所有异常都该在当前方法里“消化”。比如数据库连接失败、远程服务超时、配置文件缺失等,属于上游调用方更应关注的问题。此时catch的作用是捕获、记录、转化,而非掩盖。
- 若当前层无能力恢复(如IO异常发生在DAO层,业务层才知是否重试),应将异常向上抛,让更有上下文的层级决策
- 避免在service层catch SQLException后只打印日志就返回null——这会让controller收到意料之外的空值,引发NPE
- 可借助自定义业务异常(如UserNotFoundException)包装原始异常,既保留栈信息,又屏蔽技术细节
使用throw或throws合理传递
Java中可通过两种方式交还控制权:直接throw e(重抛原异常)或throw new XxxException("msg", e)(包装后抛出)。后者更推荐,尤其跨模块时。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 重抛适用于无需额外语义、且调用方已声明处理该异常的情况(如catch InterruptedException后立即throw)
- 包装异常时,务必把原始异常作为cause传入构造器,否则丢失根因线索
- 不要用e.printStackTrace()代替抛出——它不中断流程,也不通知调用方,等于假装没发生
必要时记录日志再抛出
捕获异常本身是观察点,记录关键上下文(如用户ID、请求参数、操作步骤)比单纯抛出更有价值。
立即学习“Java免费学习笔记(深入)”;
- 用SLF4J等日志框架记录ERROR级别日志,包含异常变量(log.error("查询用户失败,uid={}", uid, e))
- 避免在log语句中拼接e.getMessage()——会丢失堆栈;日志框架自动处理完整异常信息
- 敏感信息(密码、token)需脱敏后再记录,防止日志泄露
慎用try-catch-finally中的return干扰
在finally里写return或throw会覆盖try/catch中的异常或返回值,导致行为不可预期。
- finally适合做资源清理(如close流、unlock锁),不要在里面修改返回值或抛新异常
- 如果必须在finally中处理异常(如关闭资源时也抛IOException),应单独捕获并记录,避免影响主流程异常传播
- JDK7+推荐用try-with-resources替代手动finally关闭,更安全简洁

















