第11章异常处理
合集下载
第11章 程序错误与异常处理

11.1.2 按错误的性质和范围分类 按照错误的性质和范围,一般可以将程序错误分成功 能错误、系统错误、数据错误和代码错误。本书将主 要讨论由代码引起的程序错误。 程序设计中常见的由代码引起的程序错误一般有三种 :编译错误、运行时错误以及逻辑错误。 1. 编译错误 编译错误是指在编译的过程中出现的错误,它是由于 编写的代码不正确而产生的,如关键字书写错误、括 号不匹配、遗漏句末分号、使用无参方法遗漏小括号 等。
说明: 说明: ① try块包含可能导致异常的代码段,是必选项。 ② catch块包含异常处理代码块,为可选项,可以有 一个或者多个catch块。 ③ finally块包含异常处理后要执行的代码段(总是会 执行),也为可选项,并且只能有一个。但当存在 catch catch块(一个或者多个),finally块可以没有,而没 finally 有catch块时,必须要有finally块。 ④ try...catch...finally的执行过程为:首先执行try块包 含的语句,若没有发现异常,则继续执行finally块包 含的语句,执行完后跳出try结构;若在try块包含的语 句中发现异常,则立即转向执行catch块包含的语句, 然后再执行finally块包含的语句,执行完后跳出try结 构。
在Visual C# 2005中处理异常时,需要在代码中关注三 个部分: (1)可能导致异常的代码段(通常称为抛出异常)— —try块。 (2)当执行代码过程中发生异常时将要执行的代码段 (通常称为捕获异常)——catch块。 (3)异常处理后要执行的代码段(可选的,通常称为 结束块)——finally块。
ห้องสมุดไป่ตู้
11.2.2 调试程序举例 下面通过一个实例来学习使用Visual C# 2005的调试工 具,并且从中学到如何排查前面介绍的程序逻辑错误 的方法。 【例11-1】新建一个Windows应用程序,输入一个百 】 分制整数成绩,首先判断输入是否有效(0~100), 若无效,则弹出消息框提示“输入错误!”;否则将其 转换成等级制成绩并输出(为简化程序,本例中只分 为及格和不及格两种情况)。
第11章 错误异常处理

11.4 小结和习题
小结
错误处理一般是难免的,本章简述了在VB中如何 进行错误处理。 由于在前面的一些章节中也有提及错误处理方法, 本章从一般的角度出发讨论了如何发现、处理和 避免程序中的错误。 首先,通过一个例子讲述了如何处理错误,然后 分别讨论了设计应用程序中捕获和响应错误的例 程三个步骤:错误处理是如何分层进行的;对一 个复杂的工程,设计错误处理过程应该遵循哪些 规则;如何用Err.Raise语句进行错误传递或触发 新的错误,如何自定义错误类型;调用产生错误 操作过程时,处理结果的三种方式。 另外,擅于使用调用工具,可以提高程序的效 率。 习题 (P 习题)
11.2 错误处理程序
错误处理程序 编写错误处理例程 错误的模拟
11.2 错误处理程序
Visual Basic 执行 On Error 语句时激活错误捕获,On Error 语句指定错误处理程序。
2. 编写错误处理例程
书写错误处理例程的第一步是添加行标签,标志着错误处理例程 开始。行标签应该有一个具有描述性的名称,其后必须加冒号。 有这样一个公共约定,即把错误处理代码放置在过程末端,该过 程在紧靠行标签前方处具有 Exit Sub、Exit 函数或 Exit 属性语 句。这样,如果未出现错误,则过程可避免执行错误处理代码。
11.2 错误处理程序
有一些规则应该值得遵守:
(1)在调试代码时,对于在程序中没有代码处理具体错误的 情况,应在所有错误处理程序中使用Err对象的Raise方法重 新生成错误。由此,应用程序就可按照调用列表,试着将其 它错误处理例程中的错误加以改正。 (2)在处理错误后,如果需要明确地清除Err对象,则可用 Clear方法。当使用具有OnErrorResumeNex的联机错误处理 时,这种做法是非常必要的。VisualBasic无论何时执行任何 类型的Resume语句、ExitSub、Exit函数、Exit属性或其它 OnError语句,都可自动调用Clear方法。 (3)如果不想要另一个过程在调用列表中捕获错误,则可用 Stop语句强制终止代码。在开发环境中精制代码时,可用 Stop检查错误的上下文。 (4)编写一个故障保险的错误处理过程,所有错误处理程序 都可调用它作为最后手段,解决不能处理的错误。故障保险 的过程能够通过卸载窗体和保存数据,按顺序中断应用程序。
第11章意外的情况——异常处理

11.2.3 Java中可能会抛出异常的方法
下面的表中列举出几个会抛出异常的方法,我们先来看下这 几个简单的异常吧!
11.3 Java程序中如何处理异常
捕获异常 11.3.2 获取异常信息 11.3.3 try、catch和finally 11.3.4 异常处理举例
11.3.1
11.3.1 捕获异常
现在我们来看如果Java程序的执行过程中遇到意外,抛出的异常如何被捕获。要想处理 Java程序运行过程中抛出的异常,首先要捕获它们。前面讲过异常处理的流程当中,try区 块中的内容是异常产生并被抛出的地带。这里面产生的异常将由紧随其后的catch语句所捕 获。 1.多个catch语句的顺序,如图11.3所示 2.在多层方法调用中的异常抛出顺序 ,如图11.4所示
11.3.4 异常处理举例
前面已经将Java中异常处理的内容介绍完了,按照惯例我们 在最后会给大家提供一个实例。这个例子当中我们所做的事 情就是从终端几个学生的成绩,然后计算他们的总成绩和平 均成绩,并将所有的数据都保存到一个文件中。学生的人数 也是在程序最开始的时候由用户在终端上输入。整个过程中 有多处需要进行异常处理的情况,一起来看看吧!
11.1.2 异常处理的简单范例
Java中异常处理的过程可以抽象为4个阶段: (1)异常发生。 (2)异常捕获。 (3)异常处理。 (4)恢复正常。 这个过程可以使用下面的流程图来表示, 请大家先看看图11.1中的流程图。
…… try { … } false
Any exceptions?
true
Ready to catch()?
false
true catch() { … }
Finally { … }
第11章异常处理

第11章 异 常 处 理 其中:
(1) try:将可能出现错误的程序代码放在try块中,对try块中 的程序代码进行检查,可能会抛出一个或多个异常。因此,try 后面可跟一个或多个catch。
(2) catch:其功能是捕获异常,参数ExceptionObject是 ExceptionType类的对象,这是由前面的try语句生成的。 ExceptionType是Throwable类中的子类,它指出catch语句中所处 理的异常类型。catch捕获异常的过程中,要将Throwable类中的 异常类型和try语句抛出的异常类型进行比较,若相同,则在 catch中进行处理。
At c11_2.main(c11_2.java:11) end
第11章 异 常 处 理 11.2.2 嵌套try-catch-finally语句
Java语言的try-catch-finally语句可以嵌套,即在try块中可以 包含另外的try-catch-finally语句。
【示例程序c11_3.java】 使用嵌套的try-catch-finally语句自 行处理异常。
RuntimeException类 CheckedException类
Error子类
RuntimeException子类 CheckedException子类
图11.2 异常类的继承结构
第11章 异 常 处 理
在Java语言中所有的异常类都继承自ng.Throwable类。 Throwable类有两个直接子类:一个是Error子类,它包含Java系 统或执行环境中发生的异常,这些异常是用户无法捕捉到的异 常;另一个是Exception类,它包含了一般性的异常,如I/O异常, SQL异常,这些异常是用户可以捕捉到的异常,可以通过产生 它的子类来创建自己的异常处理。下面分别论述。
第11章 异常处理结构

fp.close()
except:
#打开文件失败时执行的代码
print('文件不存在')
11.2.4 可以捕捉多种异常的异常处理结构
• 例11-4 使用异常处理结构捕获多种可能的异常。
>>> try: x = float(input('请输入被除数: ')) y = float(input('请输入除数: ')) z=x/y
Please input:888c Error. Please input:888 You have input 888
11.2.3 try...except...finally...
• 例11-3 编写程序,接收一个文本文件的名字,预期该文件中只包含一个整 数,要求输出该数字加5之后的结果。如果文件不存在就提示不存在;如果 文件存在但内容格式不正确,就提示文件内容格式不正确。
11.1 异常的概念与表现形式
>>> len(3)
#参数类型不匹配
TypeError: object of type 'int' has no len()
>>> list(3)
#参数类型不匹配
TypeError: 'int' object is not iterable
>>> import socket
Please input:234c Error. Please input:5 You have input 5
7
11.2.2 try...except...else...
• 例11-2 使用try...except...else...结构改写例11-1的代码。
第11章 异常处理

2011/1/17
面向对象程序设计
第11章 异常处理
• • • • • • • • • • • • • • •
【例11.3】异常接口 void Xhandler(int test) throw(int, char, double) { if(test==0) throw test; // throw int if(test==1) throw 'a'; // throw char if(test==2) throw 123.4; // throw double } int main() { cout << "程序开始\n"; try { Xhandler(0); // 也可以尝试使用1或者2传递给函数 Xhandler() }
• • • 程序开始 捕获一个int型 程序结束
2011/1/17
面向对象程序设计
第11章 异常处理
• 如果在代码中出现了规范以外的异常,那么程序将非正 常终止。如果上面的代码作如下修改: • void Xhandler(int test) throw(int, char) • { • if(test==0) throw test; // throw int • if(test==1) throw 'a'; // throw char • if(test==2) throw 123.4; // throw double • //当遇到test是2的情况, • // 将导致程序非正常终止。 • }
第11章 异常处理
11.1 概述 11.2 异常接口规范说明 11.3 上机指导
主目录
第11章 异常处理
11.1 概述
C++中异常处理由try、catch和throw三个关键字 来组合实现。try代码块中书写的是被监测是否有异常 的代码,如果这些代码有异常产生,那么这个异常将 被抛(throw)出来,并且它被catch块截获处理。 被监视是否有异常的代码必须放在try代码块中执 行,这些代码中产生的异常被抛出后可以被紧跟其后 的catch语句截获。
第11章 异常处理

北京源智天下科技有限公司
1-1
联系方式:
11.1 异常处理基本介绍
在本节中将对异常有一个大概的了解.异常发生的原因有很多, 可能是软件的问题,也可以是硬件的问题.在Java程序中,对异 常的处理都是一样的,一般情况下是通过try-catch语句来进行异 常处理.该语句还可以存在finally语句.本节中就来对这些最简 单的异常处理语句进行介绍.
北京源智天下科技有限公司
1-8
联系方式:
11.1.4 再谈异常处理注意点
学习finally语句后,又多出了很多在写try-catch-finally语句 时需要注意的地方.这些在开发中是比较少见的,但是在考试中 经常会出现.第一个注意点就是当不存在catch语句时,finally 语句必须存在并且紧跟在try语句后面.读者可以自己写程序来验 证这一点. 还有一个需要注意的格式是在try语句和catch语句间不能存在任 何语句,同样在catch语句和finally语句中也不能存在任何语句 ,这地方的语句不包括注释语句. 注意:当不存在catch语句时,finally语句必须存在并且紧跟在 try语句后面.在try语句和catch语句间不能存在任何语句,同样 在catch语句和finally语句中也不能存在任何语句.
北京源智天下科技有限公司
1-5
联系方式:
当对程序使用多个catch语句进行异常处理时,特别需要注意的是 要将范围相对小的异常放在前面,将范围相对大的异常放在后面 ,这通过程序是很容易理解的. 注意:当对程序使用多个catch语句进行异常处理时,要将范围相 对小的异常放在前面,将范围相对大的异常放在后面.
北京源智天下科技有限公司
1-3
联系方式:
11.1.2 try-catch语句使用注意点
1-1
联系方式:
11.1 异常处理基本介绍
在本节中将对异常有一个大概的了解.异常发生的原因有很多, 可能是软件的问题,也可以是硬件的问题.在Java程序中,对异 常的处理都是一样的,一般情况下是通过try-catch语句来进行异 常处理.该语句还可以存在finally语句.本节中就来对这些最简 单的异常处理语句进行介绍.
北京源智天下科技有限公司
1-8
联系方式:
11.1.4 再谈异常处理注意点
学习finally语句后,又多出了很多在写try-catch-finally语句 时需要注意的地方.这些在开发中是比较少见的,但是在考试中 经常会出现.第一个注意点就是当不存在catch语句时,finally 语句必须存在并且紧跟在try语句后面.读者可以自己写程序来验 证这一点. 还有一个需要注意的格式是在try语句和catch语句间不能存在任 何语句,同样在catch语句和finally语句中也不能存在任何语句 ,这地方的语句不包括注释语句. 注意:当不存在catch语句时,finally语句必须存在并且紧跟在 try语句后面.在try语句和catch语句间不能存在任何语句,同样 在catch语句和finally语句中也不能存在任何语句.
北京源智天下科技有限公司
1-5
联系方式:
当对程序使用多个catch语句进行异常处理时,特别需要注意的是 要将范围相对小的异常放在前面,将范围相对大的异常放在后面 ,这通过程序是很容易理解的. 注意:当对程序使用多个catch语句进行异常处理时,要将范围相 对小的异常放在前面,将范围相对大的异常放在后面.
北京源智天下科技有限公司
1-3
联系方式:
11.1.2 try-catch语句使用注意点
第11章错误异常处理

11.2 错误处理程序
有一些规则应该值得遵守: 有一些规则应该值得遵守:
(1)在调试代码时,对于在程序中没有代码处理具体错误的 )在调试代码时, 情况,应在所有错误处理程序中使用Err对象的 对象的Raise方法重 情况,应在所有错误处理程序中使用 对象的 方法重 新生成错误。由此,应用程序就可按照调用列表, 新生成错误。由此,应用程序就可按照调用列表,试着将其 它错误处理例程中的错误加以改正。 它错误处理例程中的错误加以改正。 对象, (2)在处理错误后,如果需要明确地清除 )在处理错误后,如果需要明确地清除Err对象,则可用 对象 Clear方法。当使用具有 方法。 方法 当使用具有OnErrorResumeNex的联机错误处理 的联机错误处理 这种做法是非常必要的。 时,这种做法是非常必要的。VisualBasic无论何时执行任何 无论何时执行任何 类型的Resume语句、ExitSub、Exit函数、Exit属性或其它 语句、 函数、 类型的 语句 、 函数 属性或其它 OnError语句,都可自动调用 语句, 方法。 语句 都可自动调用Clear方法。 方法 (3)如果不想要另一个过程在调用列表中捕获错误,则可用 )如果不想要另一个过程在调用列表中捕获错误, Stop语句强制终止代码。在开发环境中精制代码时,可用 语句强制终止代码。 语句强制终止代码 在开发环境中精制代码时, Stop检查错误的上下文。 检查错误的上下文。 检查错误的上下文 (4)编写一个故障保险的错误处理过程,所有错误处理程序 )编写一个故障保险的错误处理过程, 都可调用它作为最后手段,解决不能处理的错误。 都可调用它作为最后手段,解决不能处理的错误。故障保险 的过程能够通过卸载窗体和保存数据,按顺序中断应用程序。 的过程能够通过卸载窗体和保存数据,按顺序中断应用程序。
第11章 异常处理

在try语句块的<语句序列>执行中如果抛掷 (throw)了异常对象,但其后没有能够捕 获该异常对象的catch语句,则由函数调用 链上的上一层函数中的try语句的catch来捕 获。
如果抛掷异常对象的throw语句不是由程序 中的某个try语句块中的<语句序列>调用的, 则抛掷的异常不会被程序中的catch捕获。
第十一章 异常处理
主要内容
异常的基本概念 C++的异常处理机制
异常概述
程序的错误通常包括:
语法错误。指程序的书写不符合语言的语法规则, 这类错误可由编译程序发现。 逻辑错误(或语义错误)。指程序设计不当造成 程序没有完成预期的功能,这类错误通过测试发 现。 运行异常。指程序设计对程序运行环境考虑不周 全而造成的程序在运行中异常终止,如:内存空 间不足、打开不存在的文件进行读操作、程序执 行了除以0的指令等等。
catch语句块要紧接在某个try语句的后面。
例如:
char filename[100]; cout << “请输入文件名:” << endl; cin >> filename; try { f(filename);//如果在函数f中抛掷了char *类型的异常, //则程序转到try后面的catch(char *str)处理。 } catch (char *str) { cout << str << “不存在!”<< endl; cout << “请重新输入文件名:” << endl; cin >> filename; f(filename); }
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
}
method1 {
... try {
... invoke method2; statement2; } catch (Exception2 ex2) { Process ex2; }
}
method2 {
... try {
... invoke method3; statement3; } catch (Exception3 ex3) { Process ex3; }
try {
statements; } catch(TheException e) {
perform operations before exits; throw e; } 语句 throw ex 重新抛出异常,所以其他处理器还有机会进行异常处理。 finally 子句 ♦ 有时不论异常是否出现或者是否被捕获,都希望执行某些代码。Java 有一个 finally 子句可以用来达到这一目的。finally 子句的语法如下所示: try { statements; } catch(TheException e) { handling e; } finally { finalStatements; } 慎用异常 ♦ 异常处理可以将错误处理代码从正常的程序编制工作中分离出来,这样可以使程序 容易阅读和修改。然而应该注意,由于异常处理需要初始化新的异常对象,需要重新返 回调用堆栈并向调用方法传递异常,所以异常处理通常需要更多的时间和资源。
2
♦ 在方法声明中使用关键字 throws 可以声明异常,如: public void myMethod() throws IOException
public void myMethod() throws IOException, OtherException
♦ 在方法头中用关键字 throws 进行声明!
1
声明,抛出和捕获异常 Java 的异常处理基于三种操作:声明异常、抛出异常和捕获异常。
method1() {
catch exception
try {
invoke method2; } catch (Exception ex) {
Process exception; }
}
method2() throws Exception {
♦ 异常:程序运行过程中出现的事件,它中断正常的程序控制流。没有异常处理代码 的程序可能非正常结束,引起严重问题。
♦ Java 给程序员提供了处理运行时错误的功能,这称为异常处理。 ♦ 例如,下面的程序会非正常终止,因为除数为 0,引起数值计算错误。
public class Test
{
public static void main(String[] args)
if (an error occurs) {
throw new Exception(); } }
claim exception throw exception
异常处理过程
♦ 一般来说,每一个方法都必须在方法头声明它可能遇到的异常类型 Error 和 RuntimeException 不需声明,这一过程称为声明异常。 ♦ 在 Java 中,当前执行的语句必然属于某个方法。当一个语句引起错误时,含有这 个语句的方法就会创建一个异常对象并将它传递给系统。异常对象包含有关异常的信 息,包括它的类型和出错时程序的状态。这一过程称为抛出异常。抛出异常分为两种 方式:系统自动抛出和用户使用 throw 语句抛出 ♦ 一个方法抛出异常后,Java 运行系统开始寻找用来处理错误的代码。处理错误的代 码称为异常处理器,从当前的方法开始,通过方法调用链向后搜索,查找这一代码。处 理器必须与抛出的异常类型相匹配,如果未发现异常处理器,程序就会终止。这个寻找 异常处理器的过程称为捕获异常。 声明异常 ♦ 声明异常就是告诉编译器在执行方法的过程中可能出现的错误。因为系统错误和运 行错误对于任何代码都可能发生,因此 Java 不要求在方法中显式的声明 Error 和 RuntimeException。如果方法要抛出其他异常,必须在方法声明中明确说明它们。 一般情况下,如果一个方法内含有可能会产生异常的语句,Java 编译器要求该方法要 么自己捕捉处理,要么在方法的首部声明可能会抛出的异常类型。 但是:Error 和 RuntimeException 两类异常既不需捕捉处理也不需在方法首部声明, Java 环境会自动处理。Error 类包括动态链接失败、虚拟机出错等异常,该类异常 Java 不 要求捕获,同时系统也不会抛出该类异常。RuntimeException 通常代表的是编程上的一些 错误,如 null reference,数组越界访问等。与 Error 类相似,运行异常(Runtime Exception) 也不需要程序对其进行捕获并处理,因为它表示 Java 虚拟机在运行时所产生的异常。该类 异常的产生非常普遍,如果在每个可能产生这种异常的地方都加以处理,程序就会变得无法 理解,从而影响程序的可读性和高效性。
的调用者。在调用者中应该捕获这个异常并进行处理。
捕获异常 ♦ 当调用一个显式声明异常的方法时,必须使用 try-catch 块括住抛出异常的语句。 try
{
statements; }
catch (Exception1 e)
{ handler for exception1
}
catch (Exception2 e)
抛出异常的例子
public double divide(double r1,double r2) throws Exception
{ if (r2 == 0)
{
throw new Exception("denominator cannot be zero"); }
return r1/r2;
}
divide()方法当分母为零时将抛出一个 Exception 异常对象,此异常被抛给 divide()方法
抛出异常 ♦ 在声明了异常的方法中,如果出现异常,就可以抛出一个异常对象。例如: throw new TheException();
或
TheException e = new TheException(); throw e;
♦ 注意:不要和 throws 弄混! ♦ 注 意 : 一 个 方 法 只 能 抛 出 在 方 法 声 明 中 声 明 的 异 常 以 及 异 常 Error 、 RuntimeException 和以上这些异常的子类。
}
♦ 如果异常在当前方法中未被捕获,就会传递给它的调用者。这个过程一直重复进行 到该异常被捕获或者传递给 main 方法。 Throwable 类的常用实例方法 ♦ public String getMessage()
返回 Throwable 对象的详细信息。 ♦ public String toString()
{
System.out.println(3/0);
}
}
♦ 测试:Test.java 异常和异常类
TestTrycatch.java
♦ 造成运行时错误的原因很多。比如,用户可能键入一个无效的输入值,程序可能试 图打开一个不存在的文件或试图访问一个越界的数组元素等。当出现一个运行时错误
时,Java 就会产生一个异常。
♦ Java 异常是 Throwable 子类的一个实例。Throwable 包含在 ng 中,它的子 类在不同的包中。与图形相关的错误包含在 java.awt 中,数值异常包含在 ng
中。扩展 Throwable 或它的子类,就能创建自己的异常类。
O b ject
T hrow able
返回 Throwable 对象的简要描述。 ♦ public void printStackTrace()
在控制台上打印 Throwable 对象和它的追踪信息。 ♦ 例:TestThrowTryCatch.java 总结: 一般情况下,如果一个方法内含有可能会产生异常的语句,并且产生的异常不是 Error 和 RuntimeException 及它们的子类,那么有两种选择:
{
3
handler for exception2 } ... catch (ExceptionN e) { handler for exceptionN } ♦ 对一段可能抛出大量不同类型的异常的程序来说,逐个捕获处理异常可能会较繁 琐,而仅仅捕获它们父类的异常则会较方便。实际使用中,需要避免捕获最一般的异常 类型(即类 Exception),因为捕获最一般的异常使得用户往往不能确切地判断异常的具 体类型并作出相应的处理。 ♦ 若程序中有多个 catch 语句,要注意它们的顺序,正确的做法是先捕获最特殊的异 常(子类异常),之后逐渐一般化(父类异常)。 ♦ 例如: try { ...} catch(Exception e) { System.out.pritnln("The error is: "+e.getMessage()); } catch(IOException e) { System.out.println("The error is: "+e); } catch (FileNotFoundException e){
A W T E rror S ev eral m o re classes
A rith m eticE x cep tio n N u llP o in terE x cep tio n
In dex O u tO fB ou nd sE x ception S ev eral m o re classes
4
1.这个方法自己捕捉异常,自行处理 try{ } catch(…) { }
2.如果自己不处理,使用 throw 语句向调用者抛出异常对象,交给调用者处理。 Example 11.1 声明,抛出和捕获异常
♦ 目的: 写一个程序测试新的 Rational 类 ♦ 源程序:TestRationalException.java Example 11.2 GUI 程序中的异常 ♦ 程序修改前,错误信息出现在控制台,但是 GUI 应用程序继续运行。 ♦ 程序修改后,如果发现除零异常,将会弹出消息对话框。 ♦ 源程序:MenuDemo 重新抛出异常 ♦ 当一个方法中出现异常时,如果它没有捕获异常,就会立即退出。如果方法在退出 前需要执行某些任务,应该在该方法中捕获异常,然后按如下结构将异常重新抛出,交 给实际处理器去处理。
method1 {
... try {
... invoke method2; statement2; } catch (Exception2 ex2) { Process ex2; }
}
method2 {
... try {
... invoke method3; statement3; } catch (Exception3 ex3) { Process ex3; }
try {
statements; } catch(TheException e) {
perform operations before exits; throw e; } 语句 throw ex 重新抛出异常,所以其他处理器还有机会进行异常处理。 finally 子句 ♦ 有时不论异常是否出现或者是否被捕获,都希望执行某些代码。Java 有一个 finally 子句可以用来达到这一目的。finally 子句的语法如下所示: try { statements; } catch(TheException e) { handling e; } finally { finalStatements; } 慎用异常 ♦ 异常处理可以将错误处理代码从正常的程序编制工作中分离出来,这样可以使程序 容易阅读和修改。然而应该注意,由于异常处理需要初始化新的异常对象,需要重新返 回调用堆栈并向调用方法传递异常,所以异常处理通常需要更多的时间和资源。
2
♦ 在方法声明中使用关键字 throws 可以声明异常,如: public void myMethod() throws IOException
public void myMethod() throws IOException, OtherException
♦ 在方法头中用关键字 throws 进行声明!
1
声明,抛出和捕获异常 Java 的异常处理基于三种操作:声明异常、抛出异常和捕获异常。
method1() {
catch exception
try {
invoke method2; } catch (Exception ex) {
Process exception; }
}
method2() throws Exception {
♦ 异常:程序运行过程中出现的事件,它中断正常的程序控制流。没有异常处理代码 的程序可能非正常结束,引起严重问题。
♦ Java 给程序员提供了处理运行时错误的功能,这称为异常处理。 ♦ 例如,下面的程序会非正常终止,因为除数为 0,引起数值计算错误。
public class Test
{
public static void main(String[] args)
if (an error occurs) {
throw new Exception(); } }
claim exception throw exception
异常处理过程
♦ 一般来说,每一个方法都必须在方法头声明它可能遇到的异常类型 Error 和 RuntimeException 不需声明,这一过程称为声明异常。 ♦ 在 Java 中,当前执行的语句必然属于某个方法。当一个语句引起错误时,含有这 个语句的方法就会创建一个异常对象并将它传递给系统。异常对象包含有关异常的信 息,包括它的类型和出错时程序的状态。这一过程称为抛出异常。抛出异常分为两种 方式:系统自动抛出和用户使用 throw 语句抛出 ♦ 一个方法抛出异常后,Java 运行系统开始寻找用来处理错误的代码。处理错误的代 码称为异常处理器,从当前的方法开始,通过方法调用链向后搜索,查找这一代码。处 理器必须与抛出的异常类型相匹配,如果未发现异常处理器,程序就会终止。这个寻找 异常处理器的过程称为捕获异常。 声明异常 ♦ 声明异常就是告诉编译器在执行方法的过程中可能出现的错误。因为系统错误和运 行错误对于任何代码都可能发生,因此 Java 不要求在方法中显式的声明 Error 和 RuntimeException。如果方法要抛出其他异常,必须在方法声明中明确说明它们。 一般情况下,如果一个方法内含有可能会产生异常的语句,Java 编译器要求该方法要 么自己捕捉处理,要么在方法的首部声明可能会抛出的异常类型。 但是:Error 和 RuntimeException 两类异常既不需捕捉处理也不需在方法首部声明, Java 环境会自动处理。Error 类包括动态链接失败、虚拟机出错等异常,该类异常 Java 不 要求捕获,同时系统也不会抛出该类异常。RuntimeException 通常代表的是编程上的一些 错误,如 null reference,数组越界访问等。与 Error 类相似,运行异常(Runtime Exception) 也不需要程序对其进行捕获并处理,因为它表示 Java 虚拟机在运行时所产生的异常。该类 异常的产生非常普遍,如果在每个可能产生这种异常的地方都加以处理,程序就会变得无法 理解,从而影响程序的可读性和高效性。
的调用者。在调用者中应该捕获这个异常并进行处理。
捕获异常 ♦ 当调用一个显式声明异常的方法时,必须使用 try-catch 块括住抛出异常的语句。 try
{
statements; }
catch (Exception1 e)
{ handler for exception1
}
catch (Exception2 e)
抛出异常的例子
public double divide(double r1,double r2) throws Exception
{ if (r2 == 0)
{
throw new Exception("denominator cannot be zero"); }
return r1/r2;
}
divide()方法当分母为零时将抛出一个 Exception 异常对象,此异常被抛给 divide()方法
抛出异常 ♦ 在声明了异常的方法中,如果出现异常,就可以抛出一个异常对象。例如: throw new TheException();
或
TheException e = new TheException(); throw e;
♦ 注意:不要和 throws 弄混! ♦ 注 意 : 一 个 方 法 只 能 抛 出 在 方 法 声 明 中 声 明 的 异 常 以 及 异 常 Error 、 RuntimeException 和以上这些异常的子类。
}
♦ 如果异常在当前方法中未被捕获,就会传递给它的调用者。这个过程一直重复进行 到该异常被捕获或者传递给 main 方法。 Throwable 类的常用实例方法 ♦ public String getMessage()
返回 Throwable 对象的详细信息。 ♦ public String toString()
{
System.out.println(3/0);
}
}
♦ 测试:Test.java 异常和异常类
TestTrycatch.java
♦ 造成运行时错误的原因很多。比如,用户可能键入一个无效的输入值,程序可能试 图打开一个不存在的文件或试图访问一个越界的数组元素等。当出现一个运行时错误
时,Java 就会产生一个异常。
♦ Java 异常是 Throwable 子类的一个实例。Throwable 包含在 ng 中,它的子 类在不同的包中。与图形相关的错误包含在 java.awt 中,数值异常包含在 ng
中。扩展 Throwable 或它的子类,就能创建自己的异常类。
O b ject
T hrow able
返回 Throwable 对象的简要描述。 ♦ public void printStackTrace()
在控制台上打印 Throwable 对象和它的追踪信息。 ♦ 例:TestThrowTryCatch.java 总结: 一般情况下,如果一个方法内含有可能会产生异常的语句,并且产生的异常不是 Error 和 RuntimeException 及它们的子类,那么有两种选择:
{
3
handler for exception2 } ... catch (ExceptionN e) { handler for exceptionN } ♦ 对一段可能抛出大量不同类型的异常的程序来说,逐个捕获处理异常可能会较繁 琐,而仅仅捕获它们父类的异常则会较方便。实际使用中,需要避免捕获最一般的异常 类型(即类 Exception),因为捕获最一般的异常使得用户往往不能确切地判断异常的具 体类型并作出相应的处理。 ♦ 若程序中有多个 catch 语句,要注意它们的顺序,正确的做法是先捕获最特殊的异 常(子类异常),之后逐渐一般化(父类异常)。 ♦ 例如: try { ...} catch(Exception e) { System.out.pritnln("The error is: "+e.getMessage()); } catch(IOException e) { System.out.println("The error is: "+e); } catch (FileNotFoundException e){
A W T E rror S ev eral m o re classes
A rith m eticE x cep tio n N u llP o in terE x cep tio n
In dex O u tO fB ou nd sE x ception S ev eral m o re classes
4
1.这个方法自己捕捉异常,自行处理 try{ } catch(…) { }
2.如果自己不处理,使用 throw 语句向调用者抛出异常对象,交给调用者处理。 Example 11.1 声明,抛出和捕获异常
♦ 目的: 写一个程序测试新的 Rational 类 ♦ 源程序:TestRationalException.java Example 11.2 GUI 程序中的异常 ♦ 程序修改前,错误信息出现在控制台,但是 GUI 应用程序继续运行。 ♦ 程序修改后,如果发现除零异常,将会弹出消息对话框。 ♦ 源程序:MenuDemo 重新抛出异常 ♦ 当一个方法中出现异常时,如果它没有捕获异常,就会立即退出。如果方法在退出 前需要执行某些任务,应该在该方法中捕获异常,然后按如下结构将异常重新抛出,交 给实际处理器去处理。