Java例外处理
辽宁经济职业技术学院信息系
硕士、副教授 陈英
异常的概念
什么是异常?
异常实际上是程序中错误,导致中断了正
常的指令流的一种事件,
在程序执行中,任何中断正常程序流程的
异常条件就是错误或异常。例如,发生下
列情况时,会出现异常:
1) 想打开的文件不存在
2) 网络连接中断
3) 受控操作数超出预定范围
4) 非常感兴趣地正在装载的类文件丢失
异常的概念
在 Java编程语言中,异常类定义程序中可能遇到
的轻微的错误条件。可以写代码来处理异常并继
续程序执行,而不是让程序中断。
一个异常通常表明出现一个错误,之所以这样称
呼是因为 java程序中的错误就是规则的异常情况。
当然异常并不总表示错误,它也可以表明在程序
中出现了一些特别不寻常的事件,需要引起特别
注意。
但并非程序中的所有错误都需要由异常来指出。
异常用于指出可能出现的不寻常的、灾难性的情
况。例如一个用户在程序中输入的信息不正确是
一种普通事件,不应该由异常来处理。
以常规方法处理错误
openFiles;
if (theFilesOpen) {
determine the lenth of the file;
if (gotTheFileLength) {
allocate that much memory;
if (gotEnoughMemory) {
read the file into memory;
if (readFailed) errorCode=-1;
else errorCode=-2; }
else errorCode=-3 }
else errorCode=-4 ; }
else errorCode=-5;
read-file {
openTheFile;
determine its size;
allocate that much
memory;
closeTheFile;
}
没有处理错
误的程序,
用异常的形式处理错误
1) 观察前面的程序你
会发现大部分精力
花在出错处理上了。
2) 只把能够想到的错
误考虑到,对以外
的情况无法处理。
3) 程序可读性差。
4) 出错返回信息量太
少。
read-File;
{ try {
openTheFile;
determine its size;
allocate that much memory;
closeTheFile;
}catch(fileopenFailed)
{ dosomething; }
catch(sizeDetermineFailed)
{dosomething;}
catch(memoryAllocateFailed)
{ dosomething;}
catch(readFailed)
{ dosomething;}
catch(fileCloseFailed)
{ dosomething; }}
异常的概念
和传统的方法比较异常的优点,
1) 把错误代码从常规代码中分离出来
2) 把错误传播给调用堆栈
3) 按错误类型和错误差别分组
4) 系统提供了对于一些无法预测的错误的捕获和处理
5) 克服了传统方法的错误信息有限的问题
method1
method2
method3
method4 产生异常


处理异常
class ExcepTest
{ public void main(String args[])
{ int b=0; int a;
try { a=4/b;}
catch(ArithmeticException e)
{
System.out.println(“divided by 0”);
} }}
Java异常继承关系图
Throwable
Error Exception
Runtime
Exception各种错误子类
Non_Runtime
Exception
各种运行
异常子类
各种非运行
异常子类
只有它的后
代才可以作
为一个异常
被抛出
由 java虚拟机
生成并抛出。
一般不作处理
可以捕获的异常不应捕获的异常
异常的分类
所有的异常都起源于 Throwable,但是
Throwable立即被分为两个分支。即使用
子类异常中的一个来描述任何特殊异常。
Error分支用于 java运行时系统的内部错误
和资源耗尽错误,它表示恢复不是不可能
但很困难的情况下的一种严重问题。比如
说内存溢出。
当一个这种内部错误发生时,除了通知用
户并试图终止程序以外基本上无能为力。
这种情况较为少见。
异常的分类
当进行 java编程时,你需要把重点放在
Exception分支上。 Exception分为两支:
1) 派生自 RuntimeException的异常。
2) 不是这样的。即 Non_Runtime Exception。
产生一个 RuntimeException的原因是编程
错误。表示一种设计或实现问题。也就是
说,它表示如果程序运行正常,从不会发
生的情况。 而任何其他异常的出现是因
为你的好程序碰上了一个意外情况,例如
一个 I/O错误等。
异常的分类
派生自 RuntimeException的异常:
1) 一个错误的造型转换。
2) 一个越界数组的访问。
3) 一个空指针访问。
非继承自 RuntimeException的异常:
1) 试图读取一个文件结尾后面的数据。
2) 试图打开一个错误的 URL。
3) 试图根据一个根本不代表任何已存在类的字符
串来找到一个 Class异常。
记住一个规则:
如果它是一个
RuntimeExceptio
n,那么这是你的
错。
异常的分类
异常是一个对象,它继承自 Throwable类,所有的
Throwable类的子孙类所产生的对象都是例外。
Throw:用户自己产生异常。
Error,由 Java虚拟机生成并抛出,Java程序不做
处理。
Exception(程序中的问题,可预知的 ):
Java编译器要求 Java程序必须捕获或声明所有的非
运行时异常。
Runtime Exception(被 0除等系统错误,数组下标超
范围 ):由系统检测,用户的 Java 程序可不做处理,
系统将它们交给缺省的异常处理程序。
异常的分类
Java语言把任何继承自 Error或 RuntimeException
的异常都称作未检查异常。
所有其他的异常都称作已检查异常。
如果数组索引扩展不超出数组界限,那么,
ArrayIndexOutOfBoundsException异常从不会抛
出。比如,这也适用于取消引用一个空值对象变
量。因为一个正确设计和实现的程序从不出现这
种异常,通常对它不做处理。
异常的分类
Throwable
Error
Exception
RuntimeException
缺省的异常
处理程序
由用户捕获或
声明并处理
不做处理
用户自己产生的异常
要处理
捕获异常
你应该捕获那些你知道如何处理的异常,而
传递那些你不知道如何处理的异常。
当你选择后者时,必须把一个 throws说明符
添加到方法声明中以告诉该方法的调用者,
一个会被抛出。
看一下 java API文档中什么方法会抛出异常,
接着再决定是处理异常,还是把它添加到
throws列表中。
不要总是自己捕获异常,把异常传递给竞争
者有时比自己处理它更好。 不要处理那些你不知
道如何处理的异常
通告被方法抛出的异常
如果 java方法碰到了它不能处理的情况,那
么它可以抛出一个异常。
一个方法不仅告诉 java编译器它能返回什么
值,还可以告诉编译器有可能产生什么错。
例如,试图读取文件的代码可能会碰到文件
不存在或者文件为空的情况,那么该方法需
要通过抛出某种 IOException来把错误通知给
编译器。
Public String readLine() throws IOException
异常分类
常见的异常
1) ArithmeticException
2) ArrayIndexOutOfBandsException
3) ArrayStoreException
4) IOException
5) FileNotFoundException
6) NullPointerException
7) MalformedURLException
8) NumberFormatException
9) OutOfMemoryException
如果在使用能够产
生异常的方法而没
有捕获和处理,将
不能通过编译
捕获并处理异常
try
{
//接受监视的程序块,在此区域内发生
//的异常,由 catch中指定的程序处理 ;
}
catch(要处理的异常种类和标识符 )
{
//处理异常 ;
}
catch(要处理的异常种类和标识符 )
{
//处理异常 ;
}
异常处理
要处理特殊的异常,将能够抛出异常的
代码放入 try块中,然后创建相应的
catch块的列表,每个可以被抛出异常
都有一个。
如果生成的异常与 catch中提到的相匹
配,那么 catch条件的块语句就被执行。
在 try块之后,可能有许多 catch块,每
一个都处理不同的异常。
finally语句
finally语句定义一个总是执行的代码块,而不
考虑异常是否被捕获。
1) try {
2) startFaucet();
3) waterLawn();
4) }
5) finally {
6) stopFaucet();
7) }
即使异常在打开
开关或给草地浇
水时发生,开关
也能被关掉。
捕获异常
finally在文件处理时非常有用
try {
对文件进行处理的程序 ;
}catch(IOException e) {
//对文件异常进行处理 ;
}finally {
不论是否发生异常,都关闭文件 ;
}
声明异常在有些情况下,一个方法并不需要处理它所生成的
异常,而是向上传递。这时就要用到 throws子句。
一个方法不处理它产生的异常,而是沿着调用层次
向上传递,由调用它的方法来处理这些异常,叫声明
异常。
声明异常的方法:
在产生异常的方法
名后面加上要抛出
(throws)的异常的
列表。
method1
computer 抛出
处理
异常
调用栈机制
Java编程语言要求,当一个方法在栈 (即它已经被调用 )上
发生 Exception(它与 Error或 RuntimeException不同 )时,
那么该方法必须决定如果出现问题该采取什么措施。
如果方法中的一个语句抛出一个没有在相应的 try/catch块
中处理的异常,那么这个异常就被抛出到调用方法中。
如果异常也没有在调用方法中被处理,它就被抛出到该方
法的调用程序。
这个过程要一直延续到异常被处理。如果异常到这时还没
被处理,它便回到 main(),而且,即使 main()不处理它,
那么,该异常就异常地中断程序。
调用栈机制
考虑这样一种情况,在该情况中 main()方法
调用另一个方法(比如,first()),然后它调
用另一个(比如,second())。
如果在 second()中发生异常,那么必须做一个
检查来看看该异常是否有一个 catch;如果没
有,那么对调用栈( first())中的下一个方法
进行检查,然后检查下一个( main())。
如果这个异常在该调用栈上没有被最后一个
方法处理,那么就会发生一个运行时错误,
程序终止执行。
调用栈机制
执行 throw语句后,运行流程立即停止,throw
的下一条语句将暂停执行。系统转向内层的一
个子 try语句块检查是否有 catch子句能匹配的
Thrwoable实例。
如果找到相匹配的实例,系统转向该子句。如
果没有找到,则转向上一层的 try语句。
这样逐层向上,直到最外层的异常处理程序中
止并打印出调用栈状况。
抛弃异常, 不是出错产生,而是人为地抛出。