Effective Java 第三版——73.抛出合乎于抽象的异常
Tips
书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code
注意,书中的有些代码里方法是基于Java 9 API中的,所以JDK 最好下载 JDK 9以上的版本。
73. 抛出合乎于抽象的异常
当一个方法抛出一个与它所执行的任务没有明显关联的异常时,这是令人不安的。在方法传播由低层(lower-level)抽象抛出的异常时,会经常发生这种情况。它不仅令人不安,而且用实现细节“污染”了上层的API。如果上层(higher layer)的实现在以后的版本中发生变化,那么它抛出的异常也会发生变化,可能会破坏现有的客户端程序。
为了避免这个问题,上层(higher layers)应该捕获低层( lower-level )的异常,并在它们的位置抛出可以用上层级别(higher-level )抽象来解释的异常。这个习语被称为异常转译:
// Exception Translation
try {
... // Use lower-level abstraction to do our bidding
} catch (LowerLevelException e) {
throw new HigherLevelException(...);
}
以下的异常转转译的示例是来自AbstractSequentialList类,该类是List接口的骨架实现(skeletal implementation )(条目 20)。 在此示例中,异常转译由List <E>
接口中的get方法规范强制要求的:
/**
* Returns the element at the specified position in this list.
* @throws IndexOutOfBoundsException if the index is out of range
* ({@code index < 0 || index >= size()}).
*/
public E get(int index) {
ListIterator<E> i = listIterator(index);
try {
return i.next();
} catch (NoSuchElementException e) {
throw new IndexOutOfBoundsException("Index: " + index);
}
}
如果较低级别的异常可能有助于调试导致较高级别异常的问题,则需要一种称为异常链(exception chaining )的特殊异常转译形式。低层异常(原因)传递给高层异常,高层异常提供一个访问器方法(Throwable的getCause方法)来检索低层异常:
// Exception Chaining
try {
... // Use lower-level abstraction to do our bidding
} catch (LowerLevelException cause) {
throw new HigherLevelException(cause);
}
高级异常的构造方法将原因传递给一个感知链(chaining-aware)的父类构造方法,因此它最终被传递给Throwable的一个感知链的构造方法,比如Throwable(Throwable):
// Exception with chaining-aware constructor
class HigherLevelException extends Exception {
HigherLevelException(Throwable cause) {
super(cause);
}
}
大多数标准异常都有感知链的构造方法。对于没有这样做的异常,可以使用Throwable的initCause方法设置原因。异常链接不仅允许你以编程方式访问原因(使用getCause),而且还将原因的堆栈跟踪集成到更高级别异常的堆栈跟踪中。
虽然异常转译优于低层异常的无意识传播,但不应过度使用。 在可能的情况下,处理较低层异常的最佳方法是通过确保较低级别的方法成功执行来避免异常。 有时可以通过检查更高级别方法的参数的有效性,然后再将它们传递到较低层来完成此操作。
如果不可能防止来自较低层的异常,那么接下来最好的事情就是让较高层静默地解决这些异常,从而使较高级别方法的调用者与较低级别的问题隔离开来。 在这些情况下,使用某些适当的日志记录工具(如java.util.logging)记录异常可能是适当的。 这允许程序员调查问题,同时把使用者和客户端代码隔离开。
总之,如果无法阻止或处理较低层的异常,那么使用异常转译,除非较低级别的方法恰好保证其所有异常都适用于较高级别。 异常链接提供了两全其美的优势:它允许抛出适当的更高级别异常,同时可以捕获失败分析的根本原因(条目 75)。
Effective Java 第三版——73.抛出合乎于抽象的异常的更多相关文章
- Effective Java 第三版——70. 对可恢复条件使用检查异常,对编程错误使用运行时异常
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- 《Effective Java 第三版》目录汇总
经过反复不断的拖延和坚持,所有条目已经翻译完成,供大家分享学习.时间有限,个别地方翻译得比较仓促,希望有疑虑的地方指出批评改正. 第一章简介 忽略 第二章 创建和销毁对象 1. 考虑使用静态工厂方法替 ...
- 《Effective Java 第三版》新条目介绍
版权声明:本文为博主原创文章,可以随意转载,不过请加上原文链接. https://blog.csdn.net/u014717036/article/details/80588806前言 从去年的3月份 ...
- Effective Java 第三版——74. 文档化每个方法抛出的所有异常
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- Effective Java 第三版——39. 注解优于命名模式
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——13. 谨慎地重写 clone 方法
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——72. 赞成使用标准异常
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- Effective Java 第三版——57. 最小化局部变量的作用域
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- Effective Java 第三版——49. 检查参数有效性
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
随机推荐
- Elasticsearch 基于 URL 的搜索请求
背景 Elasticsearch 不像关系型数据库,没有简易的 SQL 用来查询数据,只能通过调用 RESTful API 实现查询.大体上查询分为两种,基于 URL 的和基于请求主体的.基于 URL ...
- Rendering React components to the document body
React一个比较好用的功能是其简单的API,一个组件可以简单到一个return了组件结构的render函数.除了一个简单的函数之外,我们还有了一段有用且可复用的代码片段. 问题 不过有时候可能会受到 ...
- springboot2 config_toolkit 并且设置全局获取数据GlobalUtil
本文只贴相关代码段,完整代码请移步至本人github,若是喜欢,可以star给予支持 作者:cnJun 博客专栏: https://www.cnblogs.com/cnJun/ 本文实现目标 重要的配 ...
- 基于335X的UBOOT网口驱动分析
基于335X的UBOOT网口驱动分析 一.软硬件平台资料 1. 开发板:创龙AM3359核心板,网口采用RMII形式 2. UBOOT版本:U-Boot-2016.05,采用FDT和DM. 参考链 ...
- MUI + Spring MVC 实现多图片上传
后台代码,主要是SpringMVC 接收多文件上传,不是用的MutilFiles 方式,主要是因为MUI 5+ 不支持文件上传的Key是同一个名字 private String saveFile(Mu ...
- 错误解决记录------------mysql连接本地数据库显示"can't get hostname for your address"
mysql连接本地数据库遇到 can't get hostname for your address 不明原因的本地mysql数据库连接不上,总是显示can't get hostname for yo ...
- 潭州课堂25班:Ph201805201 django 项目 第二十二课 文章主页 新闻列表页面滚动加载,轮播图后台实现 (课堂笔记)
新建static/js/news/index.js文件 ,主要用于向后台发送请求, // 新建static/js/news/index.js文件 $(function () { // 新闻列表功能 l ...
- [转]OpenVPN官网的HOWTO
因为墙的原因,打不开.特此转一下: HOWTO Introduction OpenVPN is a full-featured SSL VPN which implements OSI layer 2 ...
- C++程序设计方法3:数组下标运算符重载
数组下标运算符重载 函数声明形式 返回类型operator[](参数): 如果返回类型是引用,则数组运算符调用可以出现在等式的左边,接受赋值,即: Obj[index] = value; 如果返回类型 ...
- X-factor Chains [POJ3421] [素数]
Description 给定一个正整数X, 一个长度为m的X-因子链是由m+1个整数组成的.其中 1 = X0, X1, X2, …, Xm = X 满足Xi < Xi+1 且 Xi ...