20190901 On Java8 第十五章 异常
第十五章 异常
要想创建健壮的系统,它的每一个构件都必须是健壮的。
异常概念
C++的异常处理机制基于 Ada,Java 中的异常处理则建立在 C++的基础之上(尽管看上去更像 Object Pascal)。
基本异常
异常参数
所有标准异常类都有两个构造器:一个是无参构造器;另一个是接受字符串作为参数,以便能把相关信息放入异常对象的构造器。
Throwable
是异常类型的根类。
自定义异常
对异常来说,最重要的部分就是类名。
异常与记录日志
对于异常类来说,getMessage()
方法有点类似于 toString()
方法。
异常声明
不过还是有个能“作弊”的地方:可以声明方法将抛出异常,实际上却不抛出。编译器相信了这个声明,并强制此方法的用户像真的抛出异常那样使用这个方法。这样做的好处是,为异常先占个位子,以后就可以抛出这种异常而不用修改已有的代码。在定义抽象基类和接口时这种能力很重要,这样派生类或接口实现就能够抛出这些预先声明的异常。
捕获所有异常
多重捕获
通过 Java 7 的多重捕获机制,可以将不同类型的异常使用“或”将它们组合起来,只在一个 catch
块中使用:
try {
x();
} catch (Except1 | Except2 | Except3 | Except4 e) {
process();
}
栈轨迹
printStackTrace()
方法所提供的信息可以通过 getStackTrace()
方法来直接访问,这个方法将返回一个由栈轨迹中的元素所构成的数组,其中每一个元素都表示栈中的一桢。元素 0 是栈顶元素,并且是调用序列中的最后一个方法调用(这个 Throwable
被创建和抛出之处)。数组中的最后一个元素和栈底是调用序列中的第一个方法调用。
重新抛出异常
只是把当前异常对象重新抛出,那么 printStackTrace()
方法显示的将是原来异常抛出点的调用栈信息,而并非重新抛出点的信息。要想更新这个信息,可以调用 filInStackTrace()
方法,这将返回一个 Throwable
对象,它是通过把当前调用栈信息填入原来那个异常对象而建立的。调用 fillInStackTrace()
的那一行就成了异常的新发生地了。
精准的重新抛出异常
从 Java 7 开始,允许抛出更具体的异常,即 catch 中捕捉的是父类,catch 块中可以抛出子类。
异常链
在 Throwable
的子类中,只有三种基本的异常类提供了带 cause 参数的构造器。它们是 Error
(用于 Java 虚拟机报告系统错误)、Exception
以及 RuntimeException
。如果要把其他类型的异常链接起来,应该使用 initCause0
方法而不是构造器。
DynamicFieldsException dfe = new DynamicFieldsException();
dfe.initCause(new NullPointerException());
throw dfe;
Java 标准异常
Throwable
这个 Java 类被用来表示任何可以作为异常被抛出的类。Throwable
对象可分为两种类型(指从 Throwable
继承而得到的类型):Error
用来表示编译时和系统错误(除特殊情况外,一般不用你关心);Exception
是可以被抛出的基本类型,在 Java 类库、用户方法以及运行时故障中都可能抛出 Exception
型异常。所以 Java 程序员关心的基类型通常是 Exception
。
异常的基本的概念是用名称代表发生的问题,并且异常的名称应该可以望文知意。异常并非全是在 java.lang
包里定义的;有些异常是用来支持其他像 util、net 和 io 这样的程序包,这些异常可以通过它们的完整名称或者从它们的父类中看出端倪。
特例:RuntimeException
RuntimeException
类型的异常(或者任何从 RuntimeException
继承的异常),也被称为“不受检查异常”。这种异常属于错误, 代表的是编程错误,将被自动捕获。
只能在代码中忽略 RuntimeException
(及其子类)类型的异常,因为所有受检查类型异常的处理都是由编译器强制实施的。
异常限制
当覆盖方法的时候,只能抛出在基类方法的异常说明里列出的那些异常。
异常限制对构造器不起作用。
一个出现在基类方法的异常说明中的异常,不一定会出现在派生类方法的异常说明里。这点同继承的规则明显不同,在继承中,基类的方法必须出现在派生类里,换句话说,在继承和覆盖的过程中,某个特定方法的“异常说明的接口”不是变大了而是变小了——这恰好和类接口在继承时的情形相反。
Try-With-Resources 用法
Java 7 引入了 try-with-resources
语法。
在 try-with-resources
定义子句中创建的对象(在括号内)必须实现 java.lang.Autocloseable
接口,这个接口有一个方法,close()。当在 Java 7 中引入 AutoCloseable
时,许多接口和类被修改以实现它;查看 Javadocs 中的 AutoCloseable
,可以找到所有实现该接口的类列表,其中包括 Stream
对象。
规范头中定义的每个对象都会在 try 语句块运行结束之后调用 close()
方法。
Java 5 中的 Closeable
已经被修改,修改之后的接口继承了 AutoCloseable
接口。所以所有实现了 Closeable
接口的对象,都支持了 try-with-resources
特性。
不能在资源规范头中定义了一个不是 AutoCloseable
的对象。
异常匹配
抛出异常的时候,异常处理系统会按照代码的书写顺序找出“最近”的处理程序。找到匹配的处理程序之后,它就认为异常将得到处理,然后就不再继续查找。
查找的时候并不要求抛出的异常同处理程序所声明的异常完全匹配。派生类的对象也可以匹配其基类的处理程序。
其他可选方式
异常处理的一个重要原则是“只有在你知道如何处理的情况下才捕获异常"。
所有模型都是错误的,但有些是能用的。
好的程序设计语言能帮助程序员写出好程序,但无论哪种语言都避免不了程序员用它写出了坏程序。
异常指南
应该在下列情况下使用异常:
- 尽可能使用
try-with-resource
。 - 在恰当的级别处理问题。(在知道该如何处理的情况下才捕获异常。)
- 解决问题并且重新调用产生异常的方法。
- 进行少许修补,然后绕过异常发生的地方继续执行。
- 用别的数据进行计算,以代替方法预计会返回的值。
- 把当前运行环境下能做的事情尽量做完,然后把相同的异常重抛到更高层。
- 把当前运行环境下能做的事情尽量做完,然后把不同的异常抛到更高层。
- 终止程序。
- 进行简化。(如果你的异常模式使问题变得太复杂,那用起来会非常痛苦也很烦人。)
- 让类库和程序更安全。(这既是在为调试做短期投资,也是在为程序的健壮性做长期投资。)
20190901 On Java8 第十五章 异常的更多相关文章
- “全栈2019”Java异常第十五章:异常链详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...
- Gradle 1.12 翻译——第十五章. 任务详述
有关其他已翻译的章节请关注Github上的项目:https://github.com/msdx/gradledoc/tree/1.12,或访问:http://gradledoc.qiniudn.com ...
- C++ Primer Plus学习:第十五章
第十五章 友元.异常和其他 友元 友元类 表 0-1 class Tv { public: friend class Remote; } Remote类可以使用Tv的数据成员,Remote类在Tv类后 ...
- 15第十五章UDF用户自定义函数(转载)
15第十五章UDF用户自定义函数 待补上 原文链接 本文由豆约翰博客备份专家远程一键发布
- 《Linux命令行与shell脚本编程大全》 第十五章 学习笔记
第十五章:控制脚本 处理信号 重温Linux信号 信号 名称 描述 1 HUP 挂起 2 INT 中断 3 QUIT 结束运行 9 KILL 无条件终止 11 SEGV 段错误 15 TERM 尽可能 ...
- CSS3秘笈复习:十三章&十四章&十五章&十六章&十七章
第十三章 1.在使用浮动时,源代码的顺序非常重要.浮动元素的HTML必须处在要包围它的元素的HTML之前. 2.清楚浮动: (1).在外围div的底部添加一个清除元素:clear属性可以防止元素包围浮 ...
- Gradle 1.12用户指南翻译——第四十五章. 应用程序插件
本文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
- Gradle 1.12用户指南翻译——第二十五章. Scala 插件
其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://g ...
- Gradle 1.12用户指南翻译——第三十五章. Sonar 插件
本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
随机推荐
- 初学Git——命令总结
首先,感谢廖雪峰老师制作的Git教程:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b0 ...
- python--线程锁,队列
#线程数据安全处理--同步锁 import time def sub(): global num print("ok") lock.acquire()#获取这把锁--->只有 ...
- 1121. Damn Single (25)
"Damn Single (单身狗)" is the Chinese nickname for someone who is being single. You are suppo ...
- 写了一个简单可用的IOC
根据<架构探险从零开始写javaweb框架>内容写的一个简单的 IOC 学习记录 只说明了主要的类,从上到下执行的流程,需要分清主次,无法每个类都说明,只是把整个主线流程说清楚,避免 ...
- 用doxygen+graphviz生成函数调用流程图
https://www.jianshu.com/p/fe4b6b95dca5 注意点:由于使用到了Graphviz,所以要设置Dot选项,勾选HAVE_DOT,并设置DOT_PATH为Graphviz ...
- git详细使用教程
一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. 二:SVN与Git的最主要的区别? SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以 ...
- 如何判断系统是32位还是64位的linux系统
如何判断系统是32位还是64位的linux系统 某日,需要下载个安装包,忽然忘记了自己的系统是32位还是64位的系统了,一时想不起来怎么查看时32位还是64位,呵呵,随便百度下,就发现有好多方法,这里 ...
- day5 函数
1.求全部元素的和 [1,2,1,2,3,3,3,3] 遍历 a = [1,2,1,2,3,3,3,3] sum = 0 n = len(a)-1 while n>=0: sum += a[ ...
- Java_环境变量
介绍 第一步:下载JDK 第二步:搭建环境,双击JDK安装程序 第三步:配置环境变量 第四步:检查JDK安装是否成功 介绍: .java 源文件 我们所编写的代码都在这个文件中 .class 字节码文 ...
- for循环性能测试
项目中遇到需要用for循环dom节点获取每个节点保存的数据,一共有8000多条数据,但是循环加载需要18秒左右才出来. 平时for循环中数据少感觉不出来,现在数据多了就有差别了. 部分代码如下 var ...