java异常——捕获异常+再次抛出异常与异常链
【0】README
0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java异常——捕获异常+再次抛出异常与异常链 的相关知识;
【1】捕获异常相关
1.1)如果某个异常发生的时候没有再任何地方进行捕获, 那程序就会运行终止: 并在控制台上打印出异常信息 , 其中包括异常的类型堆栈的内容;
1.2)要想捕获一个异常, 必须设置 try/catch 语句块:
- 1.2.1)如果在try语句块中抛出了一个在 catch子句中声明的异常类, 那么
- case1)程序将跳过try 语句块的其余代码;
- case2)程序将执行 catch 子句中 的处理器代码;
- 1.2.2)如果在try语句块中没有抛出任何异常, 那么程序将跳过 catch子句;
- 1.2.3)如果方法中的任何代码抛出了一个在 catch 子句中没有声明的异常类型, 那么这个方法就会立刻退出;
1.3)看个荔枝: (看一个读取文本的程序代码以演示捕获异常的处理过程)
public void read(String filename)
{
try
{
InputStream in = new FileInputStream(filename); // 创建输入流
int b;
while((b=in.read()) != -1)
process input
}
catch(IOException exception)
{
exception.printStackTrace(); // 打印栈轨迹;
}
}
对上述代码的分析(Analysis):
- A1)需要注意的是, try 语句中的大多数代码都很容易理解, 读取并处理文本行, 直到遇到文件结束符为止;(read 方法可能抛出一个IOException异常)
- A2)在这种情况下, 将跳出整个while循环, 进入 catch子句, 并生成一个 栈轨迹;
1.4)对于一个普通 的程序来说, 处理以上的对异常处理的方法外,还有其他方法吗?
- 1.4.1)通常, 最好的选择是: 什么也不做, 而是将异常传递给调用者;如果read方法出现了错误, 那就让read方法的调用者去处理。
- 1.4.2)如果采用这种方式, 就必须声明这个方法可能抛出一个 IOException(将异常传递给调用者);
public void read(String filename) throws IOException
{
InputStream in = new FileInputStream(filename); // 创建输入流
int b;
while((b=in.read()) != -1)
process input
}
Attention)编译器严格地执行 throws 说明符。 如果调用了一个抛出已检查异常的方法, 就必须对它进行处理, 或者将它继续进行传递;
1.5)对于以上两种处理异常的方法, 哪种 方法更好呢?(method1:自己处理(在可能发生异常的函数中添加try/catch 语句块);method2:将异常传递(throw)给调用者,调用者处理)
- 1.5.1)通常, 应该捕获那些知道如何处理的异常, 而将那些不知道怎么处理的异常继续进行传递;如果想传递一个异常, 就必须在方法的首部添加一个throws 说明符, 以便告知调用者这个方法可能会抛出异常;
- 1.5.2)阅读API后, 以便知道这个方法可能会抛出哪种异常, 然后再决定是自己处理, 还是添加到 throws 列表中;
Attention)以上规则有个例外: 前面提到, 如果编写一个 覆盖超类的方法, 而这个方法又没有抛出异常, 那么这个方法就必须捕获方法代码中出现的每一个已检查异常。不允许在子类的 throws 说明符中出现超过超类方法所列出的异常类范围;(也就是说父类方法没有抛出异常,你子类方法也不准抛出异常,只能自己添加 try/catch 语句块自己处理)
【2】捕获多个异常
2.1)在一个try 语句块中可以捕获多个异常, 并对不同类型的异常做出不同的处理。可以按照下列方式为每个异常类型使用一个单独的 catch 子句;
try
{}
catch(FileNotFoundException e)
{}
catch(UnknownHostException e)
{}
catch(IOException e)
{}
2.2)要想获得异常对象 的更多信息: 可以试着使用 e.getMessage() 得到详细的错误信息, 或者使用 e.getClass().getName(); 得到异常对象 的实际类型;
2.3)合并catch 子句: 在 java SE7中, 同一个 catch 子句中可以捕获多个异常类型。 例如, 假设对应缺少文件和 未知主机异常的动作是一样的, 就可以合并catch 子句:
try
{}
catch(FileNotFoundException | UnknownHostException e)
{}
catch(IOException e)
{}
Attention)
- A1)只有当捕获的异常类型彼此间不存在子类关系时 才需要这个特性;
- A2)捕获多个异常时, 异常变量隐含为 final变量。例如, 不能在以下子句体中为 e 赋不同的 值;
catch(FileNotFoundException || UnknownHostException e) {} - A3)捕获多个异常不仅会让你的代码看起来简单, 还会更高效。生成的字节码只包含一个对应公共catch 子句的代码块;
【3】再次抛出异常与异常链
3.1)在catch子句中可以抛出一个异常, 这样做的目的是 改变异常类型;
- 3.1.1)看个荔枝:
try
{}
catch(SQLException e)
{
throw new ServletException("data error : " + e.getMessage());
}
对以上代码的分析(Analysis):
- A1)这里, ServletException 用带有异常信息文本的构造器来构造;
- A2)不过, 可以有一种更好的方法, 并且将原始异常设置为新异常的原因:
try
{}
catch(SQLException e)
{
Throwable se = new ServletException("database error");
se.initCause(e);
throw se;
}
- A3)当捕获到这个异常时, 就可以使用下面的语句重新得到 原始异常:
Throwable e = se.getCause();
Attention)强烈建议使用这种包装技术, 这样可以让用户抛出子系统中的高级异常, 而不会丢失原始异常的小细节; (推荐使用 strongly recommended)
Hint)
- H1)如果在一个方法中发生了一个已检查异常,而不允许抛出它, 那么包装技术就十分有用。 我们还可以捕获这个已检查异常, 并将它包装成一个 运行时异常;
- H2)有时候, 你可能只想记录一个异常,再将它重新抛出, 而不做任何改变:
try
{
access the database
}
catch(Exception e)
{
logger.log(level, message, e);
throw e;
}
- H3)在Java SE7 之前, 将上述代码放入下述方法中, 会出现一个问题;
public void updateRecord() throws SQLException
- 因为, java 编译器查看catch 块中的 throw 语句, 然后查看e的类型, 会指出这个方法可以抛出任何Exception而不仅仅是 SQLException;
- H4)java se 7之后(编译器检测语法合法): 编译器会跟踪到 e 来自于try块中, 假设这个 try 块中仅有 的已检查异常 是 SQLException实例, 另外,假设e在catch块中未改变, 将外围方法声明为 throws SQLException 就是合法的;
java异常——捕获异常+再次抛出异常与异常链的更多相关文章
- [core java学习笔记][第十一章异常断言日志调试]
第11章 异常,断言,日志,调试 处理错误 捕获异常 使用异常机制的技巧 使用断言 日志 测试技巧 GUI程序排错技巧 使用调试器 11.1 处理错误 11.1.1异常分类 都继承自Throwable ...
- Java中的异常处理:何时抛出异常,何时捕获异常,何时处理异常?
Java中的异常处理:何时抛出异常,何时捕获异常? 2017-06-07 1 异常分类 Throwable对象可以分为两组: 一组是unchecked异常,异常处理机制往往不用于这组异常,包括: Er ...
- Java中编写代码出现异常,如何抛出异常,如何捕获异常
异常的产生过程解析 先运行下面的程序,程序会产生一个数组索引越界异常ArrayIndexOfBoundsException.我们通过图解来解析下异常产生的过程. 工具类 class ArrayTool ...
- 牛客网Java刷题知识点之什么是异常、异常处理的原理是什么、为什么要使用异常、异常体系、运行时异常、普通异常、自定义异常、异常链
不多说,直接上干货! 在这个世界不可能存在完美的东西,不管完美的思维有多么缜密,细心,我们都不可能考虑所有的因素,这就是所谓的智者千虑必有一失.同样的道理,计算机的世界也是不完美的,异常情况随时都会发 ...
- java代码异常捕获throws抛出异常
总结:Throwable 是所以异常的父类.error和Exception是继承它的类 Exception: 这类异常一般是外部错误,例如试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环 ...
- 【转】Java异常总结和Spring事务处理异常机制浅析
异常的概念和Java异常体系结构 异常是程序运行过程中出现的错误.本文主要讲授的是Java语言的异常处理.Java语言的异常处理框架,是Java语言健壮性的一个重要体现. Thorwable类所有异常 ...
- Java异常总结和Spring事务处理异常机制浅析
异常的概念和Java异常体系结构 异常是程序运行过程中出现的错误.本文主要讲授的是Java语言的异常处理.Java语言的异常处理框架,是Java语言健壮性的一个重要体现. Thorwable类所有异常 ...
- Java核心知识体系3:异常机制详解
1 什么是异常 异常是指程序在运行过程中发生的,由于外部问题导致的运行异常事件,如:文件找不到.网络连接失败.空指针.非法参数等. 异常是一个事件,它发生在程序运行期间,且中断程序的运行. Java ...
- Effective java笔记(八),异常
57.只针对异常的情况才使用异常 try { int i = 0; while(true) range[i++].climb(); }catch(ArrayIndexOutOfBoundsExcept ...
随机推荐
- Intellij IDEA中修改项目名称
如下图红色标识所示: 修改方法见下图:
- android图片特效处理之怀旧效果
图片特效处理系列将介绍图片的像素点的特效处理,这些物资注重的是原理.也就是说只要你知道这些算法不管是C++,VB,C#,Java都可以做出相同的特效.下面将介绍图片怀旧效果的算法.算法如下: 上面公式 ...
- BZOJ1014[JSOI2008]火星人prefix(splay维护hash)
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...
- mysql 多实例案例实战
其实Mysql多实例就是在一个 mysql 服务上面启动三个实例,相当于三个分离开来的数据库,至于为什么要做这个,你也可以选择分别安装三个MySQL,只是过于麻烦,多实例中只需要一个配置档my.cnf ...
- 强连通分量分解 Kosaraju算法 (poj 2186 Popular Cows)
poj 2186 Popular Cows 题意: 有N头牛, 给出M对关系, 如(1,2)代表1欢迎2, 关系是单向的且能够传递, 即1欢迎2不代表2欢迎1, 可是假设2也欢迎3那么1也欢迎3. 求 ...
- eclipse中导入zico Maven项目
zico源代码地址:https://github.com/jitlogic/zico 简单的说,git上同步的源代码需要先进行maven编译,然后导入eclipse. 如果没有配置好maven,请参考 ...
- React评论展示案例(包含知识点:state、props、ref、React声明周期、localStorage本地存储等)
本案例在上一篇的案例(React组件之间通过Props传值的技巧(小案例,帮助体会理解props.state.受控组件和非受控组件等))的基础上加强功能和用户体验,但是当然还有很多需要改进的地方,后期 ...
- pt模型
top-down
- cdn缓存
1:缓存是什么? 首先.看看没有站点没有接入CDN时.用户浏览器与server是怎样交互的: 假设中间加上一层CDN,那么用户浏览器与server的交互例如以下: client浏览器先检查是否有本地缓 ...
- 电脑c盘清理
https://www.cnblogs.com/btchenguang/archive/2012/01/20/2328320.html