第8章 异常

一个定义良好的API,应该包含了使用该方法的前置条件和后置条件。然而,程序运行的环境是复杂的,程序在执行过程中可能遇到各种错误。为此,源代码要为可能遇到错误做一些准备。编程时要预见到:方法执行时可能会遇到意外情况。错误的根源,可能是不恰当的外部环境,可能是方法调用者传递了不恰当的实参——即错误环境非法参数

服务的设计者,必须考虑到可能发生的异常事件、必须考虑抛出异常对象、做好本方法的文档使方法具有良好的接口

方法的设计者有义务对 方法参数的有效性进行检查。不管方法的文档中是否使用前置条件对参数加以明确地说明,非法参数的检查是方法实现的第一步。

假设不采用异常对象而使用传统的错误处理机制(例如C语言那样),charAt()就得给异常事件返回一个特殊的值,调用者判断该返回值以处理异常,请现在就阅读[例程 8-4代码混杂] (例程放在[8.1.4自定义异常类]中是为了便于比较传统手段和自定义异常)。这种传统手段存在诸多问题:

  • 代码混杂。正常的功能代码与大量的、对系统中可能出现的各种错误进行处理的代码混杂在一起,严重降低了程序的可读性。将业务逻辑与异常处理分离,可以说是Java异常机制最重要的目的。
  • 同一个错误没有加以数据抽象。以某种数据类型封装异常或错误,而不是将检测同一个错误的代码分布在程序的各个角落,能够有效地增强复用性。标准的异常类库的建设,使程序员不再需要在异常处理问题上花太多精力。
  • 特殊的返回值问题。

所以传统语言如C,处理异常比较麻烦。有人利用强大的setjmp和longjmp函数,并大量地应用宏以达到C++和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异常的补充材料。在相关小节中补充。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值