发布于2026-06-18 阅读(0)
扫一扫,手机访问
先聊一个Ja va异常处理里经常遇到的编译期小“陷阱”——多catch块的顺序写反了,IDE直接报错“exception XXX has already been caught”。别慌,这不是运行时才暴露的bug,而是编译器在做一项静态检查:它要确保每一个catch块都是“可达”的。规则很简单:子类异常必须写在父类前面,否则后面那个子类的catch块就成了永远不会执行的死代码,编译器自然要亮红灯。

这个问题的本质就这么纯粹——只需调整catch声明的顺序,错误立刻消失。它跟调试、跟程序逻辑都无关,纯粹是类型匹配的优先级问题。
Ja va的catch匹配机制是“从上往下”逐个检查异常类型的。一旦某个catch块匹配成功,就执行它的逻辑,然后直接跳出整个try块,不会再往下检查。这也就意味着,如果你把Exception写在IOException前面,那么所有IOException的实例(甚至包括它的子类)都会被Exception的catch块“截胡”,后面的IOException块自然就成了不可达代码。
所以说,规则非常明确:
FileNotFoundException必须写在IOException之前IOException必须写在Exception之前ArithmeticException必须写在RuntimeException之前SQLException和IOException),它们的顺序是可以互换的,不会影响编译从Ja va 7开始,支持在一个catch里处理多个不相关的异常类型,语法上用竖线分隔。不过这里也有个硬性要求:这些异常类型之间不能有继承关系。它们必须是“互不相干”的才行,否则编译器直接报错:“alternative exception types must be disjoint”。
通俗讲:
catch (IOException | SQLException e)——二者无继承,合法catch (IOException | FileNotFoundException e)——后者是前者子类,非法Exception),所以你不能直接调用某个子类的特有方法,除非做强制类型转换catch (Exception e)或者catch (Throwable t)这种广义的catch块,不是不能用,但前提是——它必须放在所有具体异常处理的后面。一旦把它往前提,后面的catch块全都变成摆设,直接无法通过编译。
即便语法上允许你把它放在最后,从代码的可维护性角度讲,也得慎用。更明智的做法是:
UserNotFoundExceptionIOException、SQLExceptionIllegalArgumentException)单独处理,有助于精准定位问题如果一时拿不准两个异常之间到底是不是父子关系,其实不用硬记。这里有几个很实用的排查技巧:
extends后面的父类是谁就清楚了
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8