前言

在 Java 开发中,代码运行时难免出现空指针、数组下标越界等意外情况,这类非正常现象就是异常。Java 提供了一套完整的异常处理机制,既能避免程序直接崩溃,又能精准定位问题,同时它也是面试高频考点。本文结合基础概念、分类、使用方式及核心规则,系统梳理 Java 异常相关知识,帮助开发者夯实基础、应对面试。

Java 所有异常与错误的顶层父类是Throwable,位于java.lang包下,它提供了getMessage()获取异常描述、printStackTrace()打印详细堆栈信息两个核心方法,前者用于前端提示,后者多用于开发调试。Throwable分为ErrorException两大分支,二者有着本质区别。

Error代表系统级严重错误,依靠代码完全无法修复,比如递归引发的StackOverflowError、JVM 内存溢出等,遇到这类错误程序只能终止,开发中无需主动捕获处理。而Exception是程序层面可处理的异常,也是我们日常开发的重点,它又细分为运行时异常和非运行时异常。

运行时异常(RuntimeException及其子类)也叫未检查异常,编译器不会强制校验,多由代码逻辑漏洞导致,像空指针异常NullPointerException、数组下标越界ArrayIndexOutOfBoundsException都属于此类。这类异常可通过优化代码规避,开发者可选择性处理。非运行时异常又称已检查异常,编译器会严格校验,代码编写阶段就必须处理,否则无法编译通过。

异常的产生与传递

异常分为自动产生和手动抛出两种形式。代码执行出错时会自动触发异常,若不做处理,程序会立刻终止,后续代码不再执行。而开发中常使用throw关键字手动抛出异常,该关键字只能写在方法内部,语法为throw new 异常类("异常信息"),执行后会终止当前方法运行。

Java 异常会沿着方法调用链反向传递,层层向上抛出,最终交由 JVM 处理,这也是程序崩溃的原因。针对异常传递,Java 提供了两种处理方案:消极处理throws和积极处理try-catch

throws用于方法声明处,作用是将异常抛给方法调用者,属于推卸式处理,虽能让编译通过,但异常依旧会导致程序终止。使用时支持用父类异常接收子类异常,简化代码编写。

try-catch-finally是主动捕获异常的核心语法。try包裹可能出错的代码,catch匹配并处理对应异常,支持多个catch块,需遵循子类异常在前、父类异常在后的规则,利用多态统一处理一类异常。finally块的代码无论是否出现异常都会执行,专门用于关闭文件流、数据库连接等资源,开发中不建议在finally中使用return,避免打乱执行逻辑。

自定义异常与方法重写规则

当原生异常无法贴合业务场景时,我们可以自定义异常。自定义异常类需继承Exception或其子类:继承RuntimeException则为运行时异常,继承普通Exception则为受检异常。规范的自定义异常必须提供无参构造和带字符串参数的构造方法,通过super()调用父类构造,传递异常描述信息。

异常在方法重写场景中有硬性约束,也是面试重中之重。子类重写父类方法时,访问权限需和父类一致或范围更大;同时子类方法不能抛出比父类范围更广、数量更多的异常,这是为了保证程序异常体系的稳定性。

总结

异常机制是 Java 保障程序健壮性的关键。区分ErrorException、理清运行时异常和受检异常的差异,是学习的基础;熟练使用throwthrowstry-catch-finally是开发必备技能;掌握自定义异常和重写的异常规则,能从容应对面试。合理处理异常,不仅可以提升代码容错性,还能快速排查线上问题,每一位 Java 开发者都需要熟练掌握这套知识体系。

更多推荐