第58条:对可恢复的情况使用受检异常,对编程错误使用运行时异常

Java程序设计语言提供了三种可抛出结构(throwable) ;受检的异常(checked exception)运行时异常(run-time exception)和错误(error)。



受检的异常是潜在指示

在决定使用受检的异常或是未受检的异常时,主要的原则是:如果期望调用者能够适当地恢复对于这种情况就应该使用受检的异常。通过抛出受检的异常,强迫调用者在一个catch子句中处理该异常。或者将它传播出去。因此,方法中声明要抛出的每个受检的异常,都是

对API用户的一种潜在指示:与异常相关联的条件是调用这个方法的一种可能的结果。

IOException、SQLException

用运行时异常来表明编程错误

有两种未受检的可抛出结构:运行时异常和错误。在行为上两者是等同的:它们都是不需要也不应该被捕获的可抛出结构。如果程序抛出未受检的异常或者错误,往往就属于不可恢复的情形,继续执行下去有害无益。如果程序没有捕捉到这样的可抛出结构,将会导致当前线程停止(halt),并出现适当的错误消息。

  1. Java.lang.ArithmeticException
  2. Java.lang.ClassCastException
  3. Java.lang.IllegalArgumentException
  4. Java.lang.IndexOutOfBoundsException

虽然JL5 (Java语言规范)并没有要求,但是按照惯例,错误往往被JVM保留用于表示资源不足、约束失败,或者其他使程序无法继续执行的条件。由于这己经是个几乎被普遍接受的惯例,因此最好不要再实现任何新的Error子类。因此,你实现的所有未受检的抛出结构都

应该是RuntimeException的子类(直接的或者间接的)。

API的设计者往往会忘记,异常也是个完全意义上的对象,可以在它上面定义任意的方法.

因为受检的异常往往指明了可恢复的条件,所以,对于这样的异常,提供一些辅助方法尤其重要,通过这些方法,调用者可以获得些有助于恢复的信息。例如,假设因为用户没有储存足够数量的钱,他企图在一个收费电话上进行呼叫就会失败,于是抛出受检的异常。这个异常应该提供一个访问方法,以便允许客户查询所缺的费用金额,从而可以将这个数值传递给电话用户。

第61条:抛出与抽象相对应的异常

异常转译

更高层的实现应该捕获低层的异常,同时抛出可以按照高层抽象进行解释的异常。这种做法被称为异常转译(exception translation ),如下所示:

下面的异常转译例子取自于AbstractSequentialList类:

异常链

一种特殊的异常转译形式称为异常链(exception chaining),如果低层的异常对于调试导致高层异常的问题非常有帮助,使用异常链就很合适。低层的异常(原因)被传到高层的异常,高层的异常提供访问方法(Throwable.getCause)来获得低层的异常:

支持链

高层异常的构造器将原因传到支持链(chaining-aware)的超级构造器,因此它最终将被传给Throwable的其中一个运行异常链的构造器,例如Throwable (Throwable):



大多数标淮的异常都有支持链的构造器。对于没有支持链的异常,可以利用Throwable的initCause方法设置原因。异常链不仅让你可以通过程序(用getCause)访问原因,它还可以将原因的堆栈轨迹集成到更高层的异常中。

第64条:努力使失败保持原子性

一般而言,失败的方法调用应该使对象保持在被调用之前的状态。具有这种属性的方法被称为具有失败原子性(failure atomic ) 。

不可变的对象

有几种途径可以实现这种效果。最简单的办法莫过于设计一个不可变的对象。

可变对象执行前先检查

对于在可变对象上执行操作的方法,获得失败原子性最常见的办法是,在执行操作之前检查参数的有效性(见第38条)。这可以使得在对象的状态被修改之前,先抛出适当的异常。



如果取消对初始大小(size)的检杳,当这个方法企图从一个空栈中弹出元素时,它仍然会抛出异常。然而,这将会导致size域保持在不一致的状态(负数)之中,从而导致将来对该对象的任何方法调用都会失败.

编写恢复代码

第三种获得失败原子性的办法远远没有那么常用,做法是编写一段恢复代码(recovery code),由它来拦截操作过程中发生的失败,以及使对象回滚到操作开始之前的状态上。这种办法主要用于永久性的(基于磁盘的(disk-based))数据结构。

临时拷贝

最后一种获得失败原子性的办法是,在对象的一份临时拷贝上执行操作。当操作完成之后再用临时拷贝中的结果代替对象的内容。

例如,Collections.sort在执行排序之前,首先把它的输入列表转到一个数组中,以便降低在排序的内循环中访问元素所需要的开销。这是出于性能考虑的做法,但是,它增加了一项优势:即使排序失败,它也能保证输入列表保持原样。

错误(相对于异常)通常是不可恢复的,当方法抛出错误时,它们不需要努力保持失败原子性。

《Effective Java》第9章 异常的更多相关文章

  1. EFFECTIVE JAVA 第十一章 系列化

    EFFECTIVE  JAVA  第十一章  系列化(将一个对象编码成一个字节流) 74.谨慎地实现Serializable接口 *实现Serializable接口付出的代价就是大大降低了“改变这个类 ...

  2. effective java 第2章-创建和销毁对象 读书笔记

    背景 去年就把这本javaer必读书--effective java中文版第二版 读完了,第一遍感觉比较肤浅,今年打算开始第二遍,顺便做一下笔记,后续会持续更新. 1.考虑用静态工厂方法替代构造器 优 ...

  3. [Effective Java]第六章 枚举和注解

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  4. [Effective Java]第七章 方法

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  5. [Effective Java]第五章 泛型

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  6. [Effective Java]第三章 对所有对象都通用的方法

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  7. [Effective Java]第四章 类和接口

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  8. java第六章异常

    异常: 程序运行一旦出现异常程序就会立刻结束不在向下运行 处理异常:在程序执行代码时,万一发生了异常,程序会按照处理的方法对一场进行处理办法,程序将继续执行 try-catch-finally-thr ...

  9. 对于所有对象都通用方法的解读(Effective Java 第三章)

    这篇博文主要介绍覆盖Object中的方法要注意的事项以及Comparable.compareTo()方法. 一.谨慎覆盖equals()方法 其实平时很少要用到覆盖equals方法的情况,没有什么特殊 ...

  10. Effective.Java第67-77条(异常相关)

    67.  明智审慎地进行优化 有三条优化的格言是每个人都应该知道的: (1)比起其他任何单一的原因(包括盲目的愚钝),很多计算上的过失都被归咎于效率(不一定能实现) (2)不要去计算效率上的一些小小的 ...

随机推荐

  1. 洛谷 P3223 [HNOI2012]排队

    题目描述 某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检.他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的) 输入输 ...

  2. spark远程调试

    基本流程1.远程运行spark,打开Spark master机器的JVM的jdwp,让其阻塞监听指定端口(8888),让其有终端向指定端口发送特定请求再执行:2.IntelliJ配置socket远程连 ...

  3. inotify 同步脚本

    #!/bin/bash path1=/home/htoa/tomcat/webapps/ROOT/htoa/ ip=192.168.30.13 /usr/bin/inotifywait -mrq -- ...

  4. linux 定时备份mysql

    定时备份:1.创建备份文件存放目录2.创建备份脚本backup.sh #!/bin/bash DBUser=db_backDBPasswd=passwordDBName=db_nameSERVER=l ...

  5. 在Azure New Portal上创建基于ARM的带SLB的VM

    目前Azure的New Portal在国内已经上线了.本文将介绍最常见的一种场景:通过Azure的New Portal创建带有Server Load Balance的多台虚拟机. 1 创建Resour ...

  6. 蓝桥杯 算法训练 ALGO-122 未名湖边的烦恼

    算法训练 未名湖边的烦恼   时间限制:1.0s   内存限制:256.0MB 问题描述 每年冬天,北大未名湖上都是滑冰的好地方.北大体育组准备了许多冰鞋,可是人太多了,每天下午收工后,常常一双冰鞋都 ...

  7. c# 遍历目录

    public static List<string> TraverseDirector(string dir, bool isTraveSubDirFlag, bool isFilterS ...

  8. [hdu4333]Revolving Digits

    /*注意注意:本题非hdu4333原题,而是简化版,原版有多组数据.但此代码在修改输入后依旧可以通过多组数据*/ 给出一个数字串,问有多少本质不同同构串比原串小,一样,大.同构串是指,对于原串S[1- ...

  9. spring的配置文件在web.xml中加载的方式

    web.xml加载spring配置文件的方式主要依据该配置文件的名称和存放的位置不同来区别,目前主要有两种方式. 1.如果spring配置文件的名称为applicationContext.xml,并且 ...

  10. 01-20Asp.net--Linq语法

    Linq语法--语言集成查询 同Sqlserver语句,但顺序颠倒了. 使用方法: 新建Linq类.dbml结尾的文件 在web窗体源代码中设计表,使用Repeater中转存放: <asp:Re ...