Java异常处理总结 - 编程一生

Java异常处理总结 - 编程一生

💡 原文中文,约9000字,阅读约需22分钟。
📝

内容提要

本文总结Java异常处理体系:Throwable分为Error和Exception,Exception又分为检查异常与非检查异常。结合代码示例介绍NPE、算术异常、未声明异常、套接字异常等典型场景,并说明Spring通过@RestControllerAdvice统一处理异常,建议梳理异常知识地图以体系化学习。

🔎

延伸解读

异常分类的实用区分法

文章指出,检查异常与非检查异常可通过编译器行为快速区分:需要显式try-catch或throws声明的就是检查异常,否则为非检查异常。Error和RuntimeException及其子类属于非检查异常,其他Exception子类为检查异常。这种区分有助于在编码时判断哪些异常必须处理,哪些可以交由统一机制兜底。

Error与Exception的处理边界

根据文章,Error通常表示JVM层面出现问题,不应捕获而应抛出,一旦发生往往导致程序停止;Exception则意味着环境正常,需要开发人员处理。这一边界提醒开发者不要盲目捕获Error,而应将异常处理重点放在Exception体系上,避免掩盖严重系统问题。

Spring统一异常处理的注意点

文章通过@RestControllerAdvice和@ExceptionHandler(Throwable.class)示例展示了统一异常处理。作者建议使用Throwable而非仅Exception,以覆盖更广的异常情况。同时提到/error路径被Spring默认占用,自定义错误页面时需避开,否则可能返回白页或意外状态码。

动态代理异常的特殊性

文章说明,使用动态代理时,若被代理类抛出未声明的检查异常,代理类会抛出UndeclaredThrowableException,其根本原因可能被包装为InvocationTargetException。作者认为这是Java动态代理不优雅的处理方式,建议在阅读或模仿源码时注意这一点,避免在业务代码中依赖此类行为。

❓

Q&A

Java异常体系中Throwable、Error和Exception的关系是什么?

Java所有异常的父类是Throwable,它分为Error和Exception。Error表示JVM层面出现的问题,正常情况下不应发生;Exception表示环境没有问题,需要开发人员处理。Exception又分为RuntimeException(运行时异常)和非运行时异常。

Java中检查异常和非检查异常如何区分?

检查异常和非检查异常的区分:Error、RuntimeException及其子类是非检查异常,其他是检查异常。写代码时,编译器提示需要try catch或throws的就是检查异常,其他是非检查异常。

Spring中如何统一处理异常?

Spring可以通过@RestControllerAdvice和@ExceptionHandler注解实现统一异常处理。例如定义一个类,使用@RestControllerAdvice标注,并在方法上使用@ExceptionHandler(Throwable.class)来捕获所有异常,返回统一格式的错误信息。

使用BigDecimal做除法时如何避免ArithmeticException?

使用BigDecimal.divide时,应使用三个参数的方法:divide(BigDecimal divisor, int scale, RoundingMode roundingMode),避免使用单参数方法。因为单参数方法在除不尽时会抛出ArithmeticException: Non-terminating decimal expansion。三参数方法会按照指定的舍入模式和保留位数处理。

Java动态代理中未声明异常是如何产生的?

使用动态代理时,如果被代理的类抛出了一个异常但没有throws声明,代理类找不到匹配的异常类型,会抛出InvocationTargetException,最终被包装为UndeclaredThrowableException。这是Java动态代理不优雅的处理方式。

Spring MVC默认如何处理404和500错误?

Spring MVC默认对不能处理的异常如404、500会返回白页。这是因为DispatcherServlet的doDispatch方法在找不到请求处理器时,会设置response状态码为404,并最终返回/error页面。

🏷️

标签

➡️

继续阅读