《Effective Java》第9章 异常
第58条:对可恢复的情况使用受检异常,对编程错误使用运行时异常
Java程序设计语言提供了三种可抛出结构(throwable) ;受检的异常(checked exception)运行时异常(run-time exception)和错误(error)。
受检的异常是潜在指示
在决定使用受检的异常或是未受检的异常时,主要的原则是:如果期望调用者能够适当地恢复对于这种情况就应该使用受检的异常。通过抛出受检的异常,强迫调用者在一个catch子句中处理该异常。或者将它传播出去。因此,方法中声明要抛出的每个受检的异常,都是
对API用户的一种潜在指示:与异常相关联的条件是调用这个方法的一种可能的结果。
IOException、SQLException
用运行时异常来表明编程错误
有两种未受检的可抛出结构:运行时异常和错误。在行为上两者是等同的:它们都是不需要也不应该被捕获的可抛出结构。如果程序抛出未受检的异常或者错误,往往就属于不可恢复的情形,继续执行下去有害无益。如果程序没有捕捉到这样的可抛出结构,将会导致当前线程停止(halt),并出现适当的错误消息。
Java.lang.ArithmeticExceptionJava.lang.ClassCastExceptionJava.lang.IllegalArgumentExceptionJava.lang.IndexOutOfBoundsException
虽然JL5 (Java语言规范)并没有要求,但是按照惯例,错误往往被JVM保留用于表示资源不足、约束失败,或者其他使程序无法继续执行的条件。由于这己经是个几乎被普遍接受的惯例,因此最好不要再实现任何新的Error子类。因此,你实现的所有未受检的抛出结构都
应该是RuntimeException的子类(直接的或者间接的)。
API的设计者往往会忘记,异常也是个完全意义上的对象,可以在它上面定义任意的方法.
因为受检的异常往往指明了可恢复的条件,所以,对于这样的异常,提供一些辅助方法尤其重要,通过这些方法,调用者可以获得些有助于恢复的信息。例如,假设因为用户没有储存足够数量的钱,他企图在一个收费电话上进行呼叫就会失败,于是抛出受检的异常。这个异常应该提供一个访问方法,以便允许客户查询所缺的费用金额,从而可以将这个数值传递给电话用户。
- 参考资料
【1】[Java受检异常和非受检异常]http://blog.csdn.net/nlznlz/article/details/53271045
【2】[Java运行时异常和非运行时异](
http://blog.csdn.net/huhui_cs/article/details/38817791)
第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章 异常的更多相关文章
- EFFECTIVE JAVA 第十一章 系列化
EFFECTIVE JAVA 第十一章 系列化(将一个对象编码成一个字节流) 74.谨慎地实现Serializable接口 *实现Serializable接口付出的代价就是大大降低了“改变这个类 ...
- effective java 第2章-创建和销毁对象 读书笔记
背景 去年就把这本javaer必读书--effective java中文版第二版 读完了,第一遍感觉比较肤浅,今年打算开始第二遍,顺便做一下笔记,后续会持续更新. 1.考虑用静态工厂方法替代构造器 优 ...
- [Effective Java]第六章 枚举和注解
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- [Effective Java]第七章 方法
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- [Effective Java]第五章 泛型
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- [Effective Java]第三章 对所有对象都通用的方法
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- [Effective Java]第四章 类和接口
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- java第六章异常
异常: 程序运行一旦出现异常程序就会立刻结束不在向下运行 处理异常:在程序执行代码时,万一发生了异常,程序会按照处理的方法对一场进行处理办法,程序将继续执行 try-catch-finally-thr ...
- 对于所有对象都通用方法的解读(Effective Java 第三章)
这篇博文主要介绍覆盖Object中的方法要注意的事项以及Comparable.compareTo()方法. 一.谨慎覆盖equals()方法 其实平时很少要用到覆盖equals方法的情况,没有什么特殊 ...
- Effective.Java第67-77条(异常相关)
67. 明智审慎地进行优化 有三条优化的格言是每个人都应该知道的: (1)比起其他任何单一的原因(包括盲目的愚钝),很多计算上的过失都被归咎于效率(不一定能实现) (2)不要去计算效率上的一些小小的 ...
随机推荐
- 浅谈FFT(快速傅里叶变换)
本文主要简单写写自己在算法竞赛中学习FFT的经历以及一些自己的理解和想法. FFT的介绍以及入门就不赘述了,网上有许多相关的资料,入门的话推荐这篇博客:FFT(最详细最通俗的入门手册),里面介绍得很详 ...
- Number Sequence (KMP的应用)
个人心得:朴素代码绝对超时,所以要用到KMP算法,特意了解了,还是比较抽象,要多体会 Given two sequences of numbers : a11, a22, ...... , aNN, ...
- Unity3d-WWW实现图片资源显示以及保存和本地加载
本文固定连接:http://blog.csdn.net/u013108312/article/details/52712844 WWW实现图片资源显示以及保存和本地加载 using UnityEngi ...
- Python函数 __import__()
功能: __import__() 函数用于动态加载类和函数 .返回元组列表. 如果一个模块经常变化就可以使用 __import__() 来动态载入. __import__ 语法: __import__ ...
- Tomcat反带和集群
Nginx|Apache反带用户请求到Tomcat LNMT: client -->http --> nginx --> reverse_proxy --> http --&g ...
- 使用spring-boot-starter-amqp开发生产者应用
上一篇我们介绍了如何使用spring AMQP和RabbitMQ结合,开发消费者应用程序,使用的是Xml配置的Spring框架. 本篇我们仍然使用Spring AMQP开发生产者应用,不过我们使用零 ...
- 删除pool error的解决方法
标签(空格分隔): ceph,ceph运维,pool 问题描述: 删除pool的时候提示下面的错误: [root@node3 ~]# ceph osd pool delete ecpool ecpoo ...
- maven学习7 settings.xml解析
maven的配置文件settings.xml存在于两个地方: 1.安装的地方:${M2_HOME}/conf/settings.xml 2.用户的目录:${user.home}/.m2/setting ...
- No result defined for action action.LoginAction and result success 问题解决
转自:https://blog.csdn.net/dongzhout/article/details/43699699 搭建好SSH2框架,写一个简单的登陆功能,提交表单的时候遇到这个问题: 配置文件 ...
- 4-EasyNetQ之Logging(黄亮翻译)
EasyNetQ提供了一个Logger接口 IEasyNetQLogger: public interface IEasyNetQLogger { void DebugWrite(string for ...