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.抛出合乎于抽象的异常的更多相关文章

  1. Effective Java 第三版——70. 对可恢复条件使用检查异常,对编程错误使用运行时异常

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  2. 《Effective Java 第三版》目录汇总

    经过反复不断的拖延和坚持,所有条目已经翻译完成,供大家分享学习.时间有限,个别地方翻译得比较仓促,希望有疑虑的地方指出批评改正. 第一章简介 忽略 第二章 创建和销毁对象 1. 考虑使用静态工厂方法替 ...

  3. 《Effective Java 第三版》新条目介绍

    版权声明:本文为博主原创文章,可以随意转载,不过请加上原文链接. https://blog.csdn.net/u014717036/article/details/80588806前言 从去年的3月份 ...

  4. Effective Java 第三版——74. 文档化每个方法抛出的所有异常

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  5. Effective Java 第三版——39. 注解优于命名模式

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  6. Effective Java 第三版——13. 谨慎地重写 clone 方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  7. Effective Java 第三版——72. 赞成使用标准异常

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  8. Effective Java 第三版——57. 最小化局部变量的作用域

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  9. Effective Java 第三版——49. 检查参数有效性

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

随机推荐

  1. VC9、VC11、VC14、VC15库 32位 64位 免费下载

    VC9.VC11.VC14.VC15库 32位 64位 免费下载 更新版本的PHP是用VC11,VC14或VC15(分别为Visual Studio 2012,2015或2017编译器)构建的,并且包 ...

  2. 总结mysql的三种外键约束方式

    如果表A的主关键字是表B中的字段,则该字段称为表B的外键,表A称为主表,表B称为从表.外键是用来实现参照完整性的,不同的外键约束方式将可以使两张表紧密的结合起来,特别是修改或者删除的级联操作将使得日常 ...

  3. 使用CCS调试基于AM335X的SPL、Uboot(原创)

    使用CCS调试基于AM335X的SPL.Uboot 一.开发环境 1.硬件平台:创龙AM3359核心板 2.SDK版本:ti-processor-sdk-linux-am335x-evm-03.00. ...

  4. AM335X启动(转)

    AM335x启动   参考文件: 1.TI.Reference_Manual_1.pdf http://pan.baidu.com/s/1c1BJNtm 2.TI_AM335X.pdf http:// ...

  5. ELK日志分析方案

    针对公司项目微服务化,随着项目及服务器的不断增多,决定采用ELK(Elasticsearch+Logstash+Kibana)日志分析平台进行微服务日志分析. 1.ELK整体方案 1.1 ELK架构图 ...

  6. Xamarin Essentials应用教程文件系统FileSystem

    Xamarin Essentials应用教程文件系统FileSystem 文件系统用于管理设备内的各类文件.通过文件系统,应用程序可以创建永久文件和临时文件,也可以获取预先打包的文件,如预设数据库文件 ...

  7. id生成器,分布式ID自增算法(Snowflake 算法)

    接口: /** * id生成器 */ public interface IdGenerator { String next(); } 实现类: /** * 分布式ID自增算法<br/> * ...

  8. IDEA中maven模块变成灰色

    可能该模块被忽略,解决办法:

  9. CentOS7.5 通过wget下载文件到指定目录

    在Linux命令行下面下载文件,通过wget是比较普遍简单的,比如在CentOS7 里面也一样. 我们先来看下自己的CentOS7 系统有没有安装wget: [root@test redis]# rp ...

  10. BZOJ1482 : [Balkan2017]Cats

    若猫和狗中至少有一个出现了$0$次,那么答案显然是$0$,否则若狮子出现了$0$次,那么显然无解. 那么现在至少有一个动物保持原地不同,其它动物恰好移动一次. 如果全部猫都不动而全部狗都动,那么可以贪 ...