一个定义明确的API,它应包括使用前后的条件的方法的。
然而,运行环境复杂。该程序可以在运行过程中遇到的各种错误。
为此,做一些准备。编程时要预见到:方法运行时可能会遇到意外情况。错误的根源,可能是不恰当的外部环境,可能是方法调用者传递了不恰当的实參——即错误环境或非法參数。
服务的设计者,必须考虑到可能发生的异常事件、必须考虑抛出异常对象、做好本方法的文档使方法具有良好的接口。
方法的设计者有义务对方法參数的有效性进行检查。无论方法的文档中是否使用前置条件对參数加以明白地说明,非法參数的检查是方法实现的第一步。
如果不採用异常对象而使用传统的错误处理机制(比如C语言那样),charAt()就得给异常事件返回一个特殊的值。调用者推断该返回值以处理异常,请如今就阅读[例程 8-4代码混杂] (例程放在[8.1.4自己定义异常类]中是为了便于比較传统手段和自己定义异常)。这样的传统手段存在诸多问题:
- 代码混杂。
正常的功能代码与大量的、对系统中可能出现的各种错误进行处理的代码混杂在一起。严重减少了程序的可读性。
将业务逻辑与异常处理分离,可以说是Java异常机制最重要的目的。
- 同一个错误没有加以数据抽象。
以某种数据类型封装异常或错误。而不是将检測同一个错误的代码分布在程序的各个角落,可以有效地增强复用性。标准的异常类库的建设,使程序猿不再须要在异常处理问题上花太多精力。
- 特殊的返回值问题。
练习8-3:说明面向对象的异常处理机制的长处。
当程序执行遇到exception,程序是就此结束执行还是应该从异常事件中恢复呢?这就得看exception的严重程度。
(1)病入膏肓就让程序安乐死,(2)大病小灾能够救死扶伤。(3)程序bug引起的(不应该出现的异常事件)则不予理会(打电话给编写那段导致异常代码的程序猿,让他改动)。
java.lang.Throwable类是 Java 语言中全部错误或异常的父类。情况(1)即严重的系统错误封装为Error、情况(3)即须要剔除的异常封装为RuntimeException。
这两种情况都不须要对异常事件加以处理,而是要在源码中寻找逻辑或使用方法错误并改动。情况(2)则是应该处理的异常。它们与情况(3)都是Exception的子类,因而Exception及其非RuntimeException子类,编译器觉得方法的调用者必须处理这类异常。也会监督、检查调用者是否处理了该异常,故称它们为被检查的异常(checked Exceptions)。一般称为检查型异常,口语化为“要处理的异常”。
所以:
- Error:程序猿不抛出、不捕捉、不处理。
- RuntimeException:由系统通过默认的异常处理程序自己主动抛出,自行处理。不强制要求程序猿捕捉和处理。
调试程序时改正。
- 检查型异常:方法头中用throws子句声明,方法体中以throw语句抛出;调用者以throws子句向上推卸处理责任、或者使用try-catch捕捉和处理。
JUnit中有非常多的样例能够作为学习Java异常的补充材料。
在相关小节中补充。
版权声明:本文博客原创文章,博客,未经同意,不得转载。