java多catch块必须子类在前、父类在后,否则编译报错“exception已捕获”;正确顺序如filenotfoundexception→ioexception→exception,确保具体异常优先匹配,避免兜底异常掩盖问题。

Java 中的多 catch 块不是炫技手段,而是提升错误定位精度和响应合理性的关键设计。它让程序能区分“文件找不到”和“读取失败”,而不是统一说“出错了”。用得好,调试时间减半;用得随意,反而掩盖问题。
按异常类型分层捕获,顺序不能错
多个 catch 块必须遵循“子类在前、父类在后”的顺序。比如 ArrayIndexOutOfBoundsException 是 RuntimeException 的子类,IOException 是 Exception 的子类。如果把通用的 catch(Exception e) 写在前面,后面更具体的异常就永远捕获不到。
- 正确写法:先写
catch(FileNotFoundException e),再写catch(IOException e) - 错误写法:把
catch(Exception e)放在最上面,其他 catch 形同虚设 - 编译器会直接报错:“已捕获的异常永远不会到达”,帮你提前发现问题
每个 catch 块只做一件事:精准响应
不同异常代表不同语义,处理方式也应不同。空指针异常往往说明逻辑缺陷,该修复代码;而网络超时可能只是临时波动,适合重试或降级。
-
catch(NullPointerException e):记录日志 + 抛出自定义业务异常,提醒开发人员检查判空逻辑 -
catch(SocketTimeoutException e):返回默认值或触发重试机制,避免阻塞主流程 -
catch(SQLException e):根据 SQLState 判断是连接中断还是语法错误,分别走熔断或告警路径
避免“兜底 catch”滥用,慎用 Exception
加一个 catch(Exception e) 看似保险,实则危险。它容易吞掉本该暴露的编程错误(如 ClassCastException),也掩盖了未预料到的异常类型,导致问题延迟发现。
- 只在顶层入口(如 Controller 方法)或日志统一拦截处使用兜底捕获
- 业务方法中尽量只捕获声明抛出的受检异常,以及明确可能发生的运行时异常
- 若真需兜底,至少记录完整堆栈:
log.error("未预期异常", e),而非仅打印消息
配合 try-with-resources,让资源管理更干净
多 catch 解决的是“怎么响应异常”,而资源释放属于“异常发生后还得保证的事”。Java 7 引入的 try-with-resources 自动关闭实现了这一点,比手动写 finally 更安全可靠。
- 优先用
try (FileInputStream fis = new FileInputStream("a.txt")) { ... } - 避免在 finally 里重复 close 资源,尤其当资源本身为 null 时易引发 NullPointerException
- 多个资源可并列声明:
try (BufferedReader br = ...; PrintWriter pw = ...) { ... }
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











