首先,你说的这个情况叫“异常屏蔽”现象。
假设有两种异常:BaseException和DerivedException。Java里每种异常都是一个类。假设前者是基类,后者是前者的派生类。就像这样,
BaseException extends Exception {}
DerivedException extends BaseException {}
try{
throw new DerivedException();
}catch(BaseException be){
//...
}catch(DerivedException de){ //彻底被屏蔽
//...
}
发生这种情况,是由Java的 “异常匹配” 机制决定的。异常匹配就是指,抛出的异常到底由哪个异常处理单元(handler)处理。主要有两大原则:
- 就近匹配原则:找到离异常异常抛出点最近的处理单元,叫被“捕获”,然后就不再往下找。
- 向上转型原则:一个特定类型的异常处理单元,可以捕捉它本身以及所有从它派生的异常。
所以根据以上两个原则,再看上面这段代码,就很清楚了,DerivedException异常抛出,根据就近匹配原则,找到最近的catch(BaseException be)处理单元。然后又根据向上转型原则BaseException处理单元可以处理它的派生异常DerivedException。然后这个异常就被捕获处理了,不在继续往下找处理单元。于是第二个处理单元就悲剧了。
这就好比你用两个盆子接水,大盆子在上,小盆子在下,那小盆子自然就一滴水也接不到。是不是这个道理?
转载自:https://www.zhihu.com/question/29472761