💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 9.8 异常匹配 “抛”出一个异常后,异常控制系统会按当初编写的顺序搜索“最接近”的控制器。一旦找到相符的控制器,就认为异常已得到控制,不再进行更多的搜索工作。 在异常和它的控制器之间,并不需要非常精确的匹配。一个派生类对象可与基类的一个控制器相配,如下例所示: ``` //: Human.java // Catching Exception Hierarchies class Annoyance extends Exception {} class Sneeze extends Annoyance {} public class Human { public static void main(String[] args) { try { throw new Sneeze(); } catch(Sneeze s) { System.out.println("Caught Sneeze"); } catch(Annoyance a) { System.out.println("Caught Annoyance"); } } } ///:~ ``` `Sneeze`异常会被相符的第一个`catch`从句捕获。当然,这只是第一个。然而,假如我们删除第一个`catch`从句: ``` try { throw new Sneeze(); } catch(Annoyance a) { System.out.println("Caught Annoyance"); } ``` 那么剩下的`catch`从句依然能够工作,因为它捕获的是`Sneeze`的基类。换言之,`catch(Annoyance e)`能捕获一个`Annoyance`以及从它派生的任何类。这一点非常重要,因为一旦我们决定为一个方法添加更多的异常,而且它们都是从相同的基类继承的,那么客户程序员的代码就不需要更改。至少能够假定它们捕获的是基类。 若将基类捕获从句置于第一位,试图“屏蔽”派生类异常,就象下面这样: ``` try { throw new Sneeze(); } catch(Annoyance a) { System.out.println("Caught Annoyance"); } catch(Sneeze s) { System.out.println("Caught Sneeze"); } ``` 则编译器会产生一条出错消息,因为它发现永远不可能抵达`Sneeze`捕获从句。 ## 9.8.1 异常准则 用异常做下面这些事情: (1) 解决问题并再次调用造成异常的方法。 (2) 平息事态的发展,并在不重新尝试方法的前提下继续。 (3) 计算另一些结果,而不是希望方法产生的结果。 (4) 在当前环境中尽可能解决问题,以及将相同的异常重新“抛”出一个更高级的环境。 (5) 在当前环境中尽可能解决问题,以及将不同的异常重新“抛”出一个更高级的环境。 (6) 中止程序执行。 (7) 简化编码。若异常方案使事情变得更加复杂,那就会令人非常烦恼,不如不用。 (8) 使自己的库和程序变得更加安全。这既是一种“短期投资”(便于调试),也是一种“长期投资”(改善应用程序的健壮性)