5 异常处理技术.docx
- 文档编号:29211147
- 上传时间:2023-07-21
- 格式:DOCX
- 页数:23
- 大小:70.90KB
5 异常处理技术.docx
《5 异常处理技术.docx》由会员分享,可在线阅读,更多相关《5 异常处理技术.docx(23页珍藏版)》请在冰豆网上搜索。
5异常处理技术
第5章异常处理技术
开发人员在进行程序设计时,程序中的各种错误的产生是不可避免的。
比如想向一个文件中写入数据,但该文件为只读文件;比如程序中加载一个类,但却找不到要加载的类等等出现这些意想不到的异常时,任何程序设计语言都要进行解决,但问题是:
●如何处理错误?
●把错误交给谁去处理?
●程序还能够继续执行吗?
1、异常的基本特性
●程序在运行过程中所发生的错误事件(如数组越界、文件操作时未找到文件、除法溢出等)
●这些错误在设计时不能准确地识别出,但运行时也许会发生或者不会发生。
●异常对象描述这种错误事件。
(当错误事件发生时,一个异常对象被创建,并且在导致该错误的方法中被抛出(利用throw),该方法可以选择处理该异常,也可以传递该异常给方法调用者)。
2、正确理解程序设计中的三种错误
(1)语法错误(编译时的错误,可以由IDE工具及时提示出)
(2)逻辑错误(运行时的错误,可以在IDE中通过调试而发现出)
(3)异常错误(运行时的错误,取决于执行环境,那我们对它又是如何处理呢?
)
3、异常处理的优点
(1)能将错误处理代码与“常规”代码相分离;
异常处理规定把错误发生时所要的细节工作与程序的主逻辑代码分离。
在传统程序中,错误的发现、报告和处理经常使得代码混乱。
例如,思考下面的代码,这是一个把某个文件读入内存的方法,如下列所示的伪代码。
readFile{
openthefile;
determineitssize;
allocatethatmuchmemory;
}
一眼看上去,这个函数似乎很简单,但是它却忽略了以下这些错误发生时程序的去向。
●如果打不开文件,应该怎么办。
●如果不能判定文件的大小,应该怎么办。
●如果没有足够的内存,应该怎么办。
要处理这些情况,需要用更多的代码来做错误的发现、报告和处理工作。
如下所示的伪代码。
readFile{
initializeerrorCode=0;
openthefile;
if(theFileIsOpen){
determinethelengthofthefile;
if(gotTheFileLength){
allocatethatmuchmemory;
if(memoryAllocationFailed){
errorCode=-1;
}
}else{
errorCode=-2;
}
}else{
errorCode=-3;
}
returnerrorCode;
}
可以看到,有非常多的错误发现、报告以及返回的情况可能会出现,使得原先只有5行的代码淹没在混乱的错误代码之中。
更严重的是,代码的逻辑已经没有了。
如果readFile函数使用异常处理来代替传统的错误管理技术,它就会变成如下伪代码所示的这样清晰和一目了然。
readFile{
try{
openthefile;
determineitssize;
allocatethatmuchmemory;
}catch(fileOpenFailed){
doSomething;
}catch(sizeDeterminationFailed){
doSomething;
}catch(memoryAllocationFailed){
doSomething;
}
}
注意:
异常处理不会节省错误的发现、报告和处理的工作量,但是它们能够帮助更有效地组织代码。
能将错误沿调用栈向上传播;
(2)异常处理的第二个优势是向方法的调用栈上层传递错误报告的能力
(3)catch块可以对异常进行分类捕捉,这样能够具有针对性的对异常进行报告处理
例如,FileNotFoundException异常类代表不能在本地磁盘上找到一个文件。
catch(FileNotFoundExceptione){
...
}
通过在catch子句中所指定的任何异常的超类的一般类型来捕获异常。
例如,要捕获所有的I/O异常,而不管它们的具体类型,就可以在异常处理代码块中指定一个IOException参数,如下所示代码。
catch(IOExceptione){
...
}
这个catch块将捕获所有的I/O异常,包括FileNotFoundException和EOFException等所有IOException类的子类。
能够通过查询传递给catch块的参数找到发生错误的详细信息。
例如,打印方法调用栈信息,如下所示代码。
catch(IOExceptione){
e.printStackTrace(); //Sytem.erre.printStackTrace(System.out); //System.out
}
甚至可以创建一个能够处理任意类型的异常的异常处理代码块,如下所示代码。
catch(Exceptione){
...
}
Exception类是Throwable类结构中的顶级类,因此,这个catch块将捕获除了那些被特定处理器捕获的异常以外的异常。
读者可能想既然这样,不如让所有的程序都采用这种简单的能捕获任意类型异常的catch块方法好了。
但是,在大多数情况下,需要异常处理尽可能处理精确一些。
原因是在catch块中编写异常处理代码的时候,必须首先判断发生异常的类型是什么,然后再针对这种类型对症下药。
在没有捕获特定错误的情况下,处理器必须有效地提供任意的可能性,遍历所有异常出现的情况。
Exception异常是最一般的异常,使用这种捕获类型,catch块将捕获和处理更多的程序员没有预料到的错误,从而使得catch块的编写失去了目的性。
(4)有利于程序的调试并且可以实现在程序出现异常时正常结束程序的流程
在用传统的语言编程时,程序员只能通过函数的返回值来发出错误信息。
这易于导致很多错误并且在很多应用情况下,还需要知道错误产生的内部细节。
这些,是通过函数的返回值所无法达到的。
5.2Java的异常处理机制
1、throws、throw、try、catch、finally
1异常事件产生于某个运行过程,因此一定在方法体中产生异常对象。
2产生异常对象后,要么抛给方法调用者,要么处理掉。
方法抛出异常的代码一般结构
publicvoid方法名()throws异常类型1,异常类型2{
…
throw异常类型1对象;
…
throw异常类型2对象;
}
方法中处理异常的一般结构
try{
有可能出现异常的常规程序代码
}catch(异常类型1异常的变量名1){
处理异常(变量名1)的程序代码
}catch(异常类型2异常的变量名2){
处理异常(变量名2)的程序代码
}finally{
无论try块中有无异常,finally块一定会执行
}
注意:
finally语句块无论try语句块中是否有异常抛出,都一定会执行,当然肯定是在return之前执行,从而达到提供统一的出口(如关闭文件、清除系统资源等)。
2应用例子
(1)try/catch/finally结构的代码示例
importjava.io.*;
publicclassExceptionDemo{
publicstaticvoidmain(Stringargs[]){
FileInputStreamfis=null;
try{//划定程序出所可能产生的异常范围
System.out.println("firstargumentis"+args[0]);
fis=newFileInputStream("text");
System.out.println("contentoftextis:
");
intdata;
while((data=fis.read())!
=-1)
{
System.out.println((char)data);
}
}
catch(FileNotFoundExceptione){//捕获程序中所可能产生的各种异常
System.out.println(e);
}
catch(IOExceptione){//注意各个catch的摆放的前后位置的要求
System.out.println(e);
}
catch(IndexOutOfBoundsExceptione){
System.out.println(e);
}
finally{//统一的出口
if(fis!
=null){
System.out.println("Closingfile…");
try{
fis.close();
}catch(IOExceptione){
System.out.println(e);
}
}
else{
System.out.println("FileInputStreamnotOpen!
");
}
}
}
}
(2)try/catch结构的代码示例
publicclassTest{
publicstaticvoidmain(String[]args){
int[]myInt=newint[10];
for(inti=1;i<=10;i++){//ifi<=10则进入循环体
System.out.println("i="+i);
try{
myInt[i]=i;//可能发生异常的位置
}
catch(ArrayIndexOutOfBoundsExceptione){
System.out.println("重新设定下标为-1");
i=-1;//重新设定为-1
}
}
}
}
(3)throw/throws应用代码示例
publicvoidwriteinfo(Stringtext)throwsIOException{
dos.writeUTF(text);
}
5.3Java中的异常类的层次结构
1、Java中的异常类的层次结构图
java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
java.lang.Error
java.lang.ThreadDeath
2、Throwable类
Throwable类是Java语言中所有错误或异常的超类。
只有当对象是此类(或其子类之一)的实例时,才能通过Java虚拟机或者Javathrow语句抛出。
类似地,只有此类或其子类之一才可以是catch子句中的参数类型。
两个子类的实例,Error和Exception,通常用于指示发生了异常情况。
通常,这些实例是在异常情况的上下文中新近创建的,因此包含了相关的信息(比如堆栈跟踪数据)。
3、Error类
Error是Throwable的子类,表示仅靠程序本身无法恢复的严重错误,用于指示合理的应用程序不应该试图捕获的严重问题。
在执行该方法期间,无需在方法中通过throws声明可能抛出但没有捕获的Error的任何子类,因为Java编译器不去检查它,也就是说,当程序中可能出现这类异常时,即使没有用try...catch语句捕获它,也没有用throws字句声明抛出它,还是会编译通过。
4、Exception类
Exception类及其子类是Throwable的一种形式,它指出了合理的应用程序想要捕获的条件,表示程序本身可以处理的异常。
5、RuntimeException类
RuntimeException是那些可能在Java虚拟机正常运行期间抛出的异常的超类。
Java编译器不去检查它,也就是说,当程序中可能出现这类异常时,即使没有用try...catch语句捕获它,也没有用throws字句声明抛出它,还是会编译通过,这种异常可以通过改进代码实现来避免。
importjava.io.*;
importjava.util.Date;
publicclassExceptionTest{
publicstaticvoidprocessCheckedException(){//对于checkedException的处理方式
/*也可以在此处将异常抛出throwsEOFException,FileNotFoundException,IOException*/
try{
DataInputStreaminput=newDataInputStream(
newFileInputStream(newFile("c:
\\data.ini")));
input.readInt();
}//异常的排列的顺序从子类到父类
catch(EOFExceptione){
e.printStackTrace();
}catch(FileNotFoundExceptione){
e.printStackTrace();
}catch(IOExceptione){
e.printStackTrace();
}finally{
System.out.println("总要被执行的代码");
}
}
publicstaticvoidprocessRunTimeException(){//对于runTime异常处理方式
Strings=null;
if(null!
=s){//避免出现NullPointerException
s.trim();
}
Objecto=newString("123");
if(oinstanceofString){//避免出现ClassCastException
Stringstr=(String)o;
}
String[]ary=newString[2];
if(2 ary[2]="123"; } } } 5.4Java中异常编程规则 1、处理多个catch块 当多个catch块时,应从特殊到一般进行匹配(先将特殊类型的异常事件放在前面,再一般类型的异常事件)。 2、try与catch之间不能有其他语句(不能被隔断) try{ } intx=1;//错误,不能被隔断 catch(Exceptione) { } 3、方法中如果产生异常对象,可以向方法调用者抛出,也可以直接处理掉 4、如果有必须要执行的代码,比如断开数据库连接操作,那么应将代码写在finnally块中,以保证它的运行 5、RuntimeException及子类异常由jvm自动处理,其余异常需要程序员手动抛出或处理 6、体现Java中异常编程规则的代码示例 packageexception; importjava.sql.SQLException; publicclassExceptionDemo{ publicvoiddataDealFun(intx)throwsSQLException,Exception{ if(x<0){ Exceptione=newException("分数<0"); throwe;//抛出异常对象 }elseif(x>100){ SQLExceptione=newSQLException("分数>100"); throwe; }else{ System.out.println(x); } } publicstaticvoidmain(String[]args){ System.out.println(12/0);//ArithmeticException类型,不需要捕捉处理 //需要处理的java异常都是在方法中产生,抛出或处理 ExceptionDemooneExceptionDemo=newExceptionDemo(); try{ f.dataDealFun(20); f.dataDealFun(320);//try{}内,该行以下的代码全部略过 f.dataDealFun(20); f.dataDealFun(20); f.dataDealFun(20); }catch(SQLExceptione){//先捕捉特殊类型的异常 e.printStackTrace(); }catch(Exceptione){//后捕捉一般类型的异常 e.printStackTrace(); }finally{//无论有没有异常都能够运行的代码块 System.out.println("****"); } //主线程继续运行 System.out.println("*******"); System.out.println("*******"); } 如果调用者方法接收到被调用者方法抛来的异常,可以直接进行处理,也可以继续向上一级调用者抛出。 如下代码: //直接处理 publicvoidinputData(intx){ try{ this.dataDealFun(x); }catch(SQLExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }catch(Exceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } /*或者向上一级抛出 publicvoidinputData(intx)throwsSQLException,Exception{ this.dataDealFun(x); } */ } 5.5声明自己的异常类 1、编程要求 (1)必须继承Exception类或其子类; (2)扩充自己的异常类的成员变量或成员方法,以反映更加丰富的异常信息以及对异常对象的处理功能。 2、体现自定义异常类的代码示例 (1)自定义异常类的代码示例一 publicclassMyException{ publicstaticvoidmain(String[]s){ MyExceptionmp=newMyException(); try{ mp.getScore(120); }catch(TooHighe){ e.printStackTrace(); System.out.println(e.getMessage()+"scoreis: "+e.score); }catch(TooLowe){ e.printStackTrace(); System.out.println(e.getMessage()+"scoreis: "+e.score); } } publicvoidgetScore(intx)throwsTooHigh,TooLow{ if(x>100){ TooHighe=newTooHigh("score>100",x); throwe; }elseif(x<0){ TooLowe=newTooLow("score<0",x); throwe; }else{ System.out.println("scoreis: "+x); } } } classTooLowextendsException{ intscore;//扩成异常类成员变量,表达更多的异常信息 publicTooLow(Stringmes,intscore){ super(mes); this.score=score; } } classTooHighextendsException{ intscore; publicTooHigh(Stringmes,intscore){ super(mes); this.score=score; } } (2)自定义异常类的代码示例二 /***从命令行获取两个数据,进行除法,如果分母为0或输入不是两个参数,均抛出异常*/ publicclassExceptionDemo1{ publicvoiddoDivision(String[]data)throwsJsError{ if(data.length! =2){ thrownewJsError("请输入两个参数"); }elseif(Integer.parseInt(data[1])==0){ //Integer.parseInt()字符串类型转换成int型 //Double.parseDouble()或Float.parseFloat() thrownewJsError("分母为0"); }else{ System.out.println(Integer.parseInt(data[0])/Integer.parseInt(data[1])); } } publicstaticvoidmain(String[]args){ ExceptionDemo1exc=newException
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 异常处理技术 异常 处理 技术