版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第八章异常处理1第八章异常处理8.1异常概述
8.2异常类
8.3异常抛出
8.4异常的捕获与处理
8.5异常处理的进一步讨论
8.6提高与总结
28.1异常概述8.1.1异常的概念8.1.2异常处理机制
3
异常是方法代码运行时出现的非正常状态,这种非正常状态使程序无法或不能再正常地继续往下运行。一些常见的异常包括:数组下标越界、除数为零、内存溢出、文件找不到等。这些异常事件发生后,会导致程序中断,使程序无法或不能正常运行下去,出现返回错误的运行结果、死循环、死机、莫明其妙的终止等现象。8.1.1异常的概念4举例(没有例外处理的情况)1)classExceptionDivideBy0{2)staticvoidmethod(){
intx=0,z=10;
int
y=10/x;
System.out.println(“z=“+z);}publicstaticvoidmain(String[]args){method();
System.out.println("Aftermethod.");}11)}5Exceptioninthread"main"java.lang.ArithmeticException:/byzeroatExceptionDivideBy0.method(ExceptionDivideBy0.java:4)atExceptionDivideBy0.main(ExceptionDivideBy0.java:7)Pressanykeytocontinue...6具有例外处理的情况classExceptionDivideBy0{staticvoidmethod(){
intx=0,z=10;
try{
inty=10/x;
System.out.println(“z=“+z);
}catch(ArithmeticExceptione){
System.out.println("ArithmeticException");
}
System.out.println("Aftertry/catchblocks.");}publicstaticvoidmain(String[]args){method();
System.out.println("Aftermethod.");}}7ArithmeticExceptionAftertry/catchblocks.Aftermethod.Pressanykeytocontinue...88.1.2异常处理机制main()方法的栈结构method()方法的栈结构抛出异常对象传递顺序递捕获处理异常调用顺序用图8-1方法的调用顺序和异常的传递顺序位于栈顶的方法为正在执行的方法方法调用的出发点98.1.2异常处理机制(续)
异常处理机制:当一个方法正常执行完毕后,Java虚拟机会从调用栈中弹出该方法的栈结构,然后继续处理前一个方法。如果在执行方法的过程中抛出异常,则Java虚拟机必须找到能处理异常的catch代码块。它首先检查当前方法是否存在这样的catch代码块,如果存在,那么就执行该catch代码块;否则,Java虚拟机会从调用栈中弹出该方法的栈结构,继续到前一个方法中查找合适的catch代码块。108.1.2异常处理机制(续)
当Java虚拟机回溯到调用栈的底部方法时,如果仍然没有找到处理该异常的代码块时,按下列步骤处理:⑴调用异常对象的printStackTrace()方法,打印来自方法调用栈的异常信息。⑵如果该线程不是主线程,那么终止这个线程,其他线程继续正常运行。如果该线程是主线程,那么整个应用程序被终止。118.1.2异常处理机制(续)一般来说,一个异常处理应该完成以下三个工作(或称三部曲):⑴抛出异常:根据异常类型产生异常对象⑵捕获异常⑶处理异常128.2异常类8.2.1异常类的分类8.2.2系统定义的异常类8.2.3用户自定义的异常类8.2.4受检查的异常和不受检查的异常
138.2.1异常类的分类每个异常由类Throwable或者它的一个子类的实例表示。Throwable类是Object类的直接子类,其本身又有两个直接子类:Error与Exception类。148.2.1异常类的分类ThrowableErrorExceptionRuntimeException缺省的例外处理程序由用户捕获或声明并处理不做处理用户自己产生的例外处理158.2.2系统定义的异常类系统定义的异常类有Error类、RuntimeException类和Exception类,它们分别代表某一类异常类型。Error类及其子类:表示灾难性的、普通程序很难恢复的例外。一般情况下,程序员可不必理会这类异常,它们虽然很严重,但很少发生。168.2.2系统定义的异常类系统定义的异常类有Error类、RuntimeException类和Exception类,它们分别代表某一类异常类型。Error类及其子类:表示灾难性的、普通程序很难恢复的异常。
如:NoClassDefFoundError(类定义没找到异常)、NoSuchMethodError(调用不存在的方法异常)等。一般情况下,程序员可不必理会这类异常,它们虽然很严重,但很少发生。178.2.2系统定义的异常类(2)RuntimeException类及其子类:表示设计或实现方面的问题。例如:ArithmeticException(算术运算异常)、ArrayIndexOutOfBoundsException(数组下标越界异常)、NullPointerException(空引用异常)等。一般情况下,这类例外通过程序员正确的设计和实现是可以避免的。188.2.2系统定义的异常类(3)Exception类及其非RuntimeException子类:表示运行时因环境的影响而引发的异常,例如:●IOException(输入输出异常):在I/O操作失败或者被中断时引发。其子类包括:EOFException、FileNotFoundException、InterruptedIOException等。●InterruptedException(中断异常):当前等待或睡眠线程被其他线程中断时引发。这类异常并非因设计或实现引起,是无法避免的。但一般情况下,程序员应该提供相应的代码捕捉和处理。198.2.3用户自定义的异常类创建用户自定义异常时,一般需要完成如下工作:⑴定义一个新的异常类,一般作为Throwable或Exception类的子类,不作为Error的子类。⑵为新的异常类定义属性和方法,或隐藏父类的属性和覆盖父类的方法,使这些属性和方法能够体现该类所对应的错误信息。自定义异常类的格式为:classMyException
extends
Exception{…//定义新的成员变量…//定义构造方法…//覆盖原方法,或定义新方法}208.2.3用户自定义的异常类其中,Exception类的属性和方法。⑴异常类的构造方法·publicException()创建新异常对象。·publicException(Stringmessage)创建包含指定异常详细消息的新异常对象。字符串参数message,描述异常对象的详细消息。·publicException(Throwablecause)创建包含指定原因的新异常对象。引用变量参数cause(原因),描述导致新异常对象抛出的异常对象。·publicException(Stringmessage,Throwablecause)创建包含指定异常详细消息和指定原因的新异常对象。218.2.3用户自定义的异常类⑵异常类的方法·publicStringtoString()返回当前异常对象的简短描述。格式为:“此异常的类名:异常的本地化描述”·publicStringgetMessage()返回描述当前异常对象的详细消息字符串。·publicvoidprintStackTrace()在屏幕上输出当前异常对象使用堆栈的轨迹,即程序中先后调用了哪些方法,使得运行过程中产生了这个异常对象。·publicThrowable
getCause()返回当前异常对象的原因(cause);如果cause不存在或未知,则返回null。·publicThrowable
initCause(Throwablecause)将当前异常对象的原因(cause)初始化为指定值。22【例8-3】设计用户自定义异常类。这样,当出现计算负数的平方根时,可输出提示信息:用户自定义异常类名:输入错误!。classMyExceptionClass
extendsException{doublex;//定义新的成员变量
MyExceptionClass(doublex){
super("输入错误!"+"x="+x+",当x的平方根为负数时引发了自定义异常。");
this.x=x;}publicStringtoString(){
return"MyExceptionClass:输入错误!";}}23【例8-4】设计用户自定义异常类。这样,当出现小时不在0~23范围之内或分秒不在0~59范围之内的情况时,可输出提示信息。classTimeExceptionextendsException{privateint
t,m,s;
TimeException(intt,intm,ints){super("时间设置错误!,当出现时分秒["+t+":"+m+":"+s+"]不在范围内时引发了自定义异常TimeException。");
this.t=t;
this.m=m;
this.s=s;}publicStringtoString(){return"TimeException:时间设置错误!["+t+":"+m+":"+s+"]";}}248.2.4受检查的异常和不受检查的异常⑴受检查的异常(编译时异常):在程序中必须对其进行处理,否则编译器会指出错误。·当一个方法中的代码抛出一个受检查的异常时,这个异常或者被方法中的try-catch结构捕获,或者在方法的throws语句中声明,并由它的调用者处理。两者必选其一,否则编译系统将给出错误信息。·编译器检查程序,保证所有受检查的异常都被程序显式地处理。ObjectThrowableErrorRuntimeExceptionException受检查异常不受检查异常子类子类子类图8-3
受检查的异常和不受检查的异常258.2.4受检查的异常和不受检查的异常⑵不受检查的异常:程序中可以不做处理,直接由运行时系统来处理。·对这类异常,程序员可以捕捉或声明抛出,但通常可以不加理会。268.3异常抛出8.3.1系统自动抛出的异常8.3.2throw语句抛出的异常
27Java应用程序在运行过程中如果出现一个可识别的错误,就会产生一个与该错误相对应的异常类对象。这个对象包含了异常的类型和错误出现时程序所处的状态信息,该异常对象首先会交给Java虚拟机,由Java虚拟机来寻找具体的异常处理者。在Java中,把产生异常对象并将其交给Java虚拟机的过程称为抛出异常。异常类不同,抛出异常的方法也不同,可分为:·系统自动抛出的异常。一般是系统定义的异常类。·throw语句抛出的异常。一般是用户自定义的异常类,也可以是系统定义的异常类。288.3.1系统自动抛出的异常Java程序运行过程中时,如果产生的错误是属于系统定义异常类所对应的一个错误,那么,系统将自动抛出该类的异常对象。例如,在例8-1中,变量y除以0的算术运算,产生的错误对应着算术异常类ArithmeticException,属于系统定义异常类。系统就会自动抛出ArithmeticException类异常对象。298.3.2throw语句抛出的异常异常既可以在发生异常情况时由运行系统引发,也可以在程序中用throw语句显式引发。throw语句的一般格式如下:throw异常对象;用throw语句抛出异常的一般过程是:⑴指定或定义一个合适的异常类。⑵产生这个类的对象并立即用throw抛出它。【例8-5】抛出不受检查的异常举例。小学生不会负数加法。当遇到负数加法时抛出异常对象。308.3.2throw语句抛出的异常classPrimaryAdd{publicdoubleadd(doublea,doubleb){
if(a<0||b<0)
thrownew
ArithmeticException("a<0||b<0"); returna+b; }}publicclassEx8_5{publicstaticvoidmain(String[]args){
PrimaryAdd
obj=newPrimaryAdd(); System.out.println("2+3="+obj.add(2,3)); System.out.println("-2+3="+obj.add(-2,3));}}31程序运行结果:2+3=5.0Exceptioninthread"main"java.lang.ArithmeticException:a<0||b<0atPrimaryAdd.add(Ex8_5.java:3)atEx8_5.main(Ex8_5.java:11)328.3.2throw语句抛出的异常【例8-6】抛出受检查的异常举例。classPrimaryAdd{publicdoubleadd(doublea,doubleb){
if(a<0||b<0)thrownew
Exception("a<0||b<0"); returna+b;}}publicclassEx8_6{publicstaticvoidmain(String[]args){
PrimaryAdd
obj=newPrimaryAdd(); System.out.println("2+3="+obj.add(2,3)); System.out.println("-2+3="+obj.add(-2,3));}}不能通过编译338.3.2throw语句抛出的异常【例8.7】抛出受检查的异常,并用throws子句声明抛出classPrimaryAdd{publicdoubleadd(doublea,doubleb)throwsException{
if(a<0||b<0)thrownewException("a<0||b<0");returna+b;}}publicclassEx8_7{publicstaticvoidmain(String[]args)throwsException{
PrimaryAdd
obj=newPrimaryAdd();System.out.println("2+3="+obj.add(2,3)); System.out.println("-2+3="+obj.add(-2,3));}}34程序运行结果:
2+3=5.0Exceptioninthread"main"java.lang.Exception:a<0||b<0atPrimaryAdd.add(Ex8_7.java:35)atEx8_7.main(Ex8_7.java:43)358.4异常的捕获与处理8.4.1try/catch语句
8.4.2多异常的捕获和处理
368.4.1try/catch语句当一个异常被抛出时,应该有专门的语句来接受这个被抛出的异常对象,这个过程被称为捕获异常。在Java程序里,异常的捕获和处理语句是同时定义的。异常对象是通过try-catch-finally语句来捕捉和处理的。该语句的语法格式如下:378.4.1try/catch语句try{//try子句是一段可能发生异常的代码,若发生异常,由catch子句捕获并处理;}//不能有其它语句分隔catch(要处理的异常类型1异常引用变量){//异常类型1对象的异常处理代码;}catch(要处理的异常类型2异常引用变量){//异常类型2对象的异常处理代码;}…finally{//总是要执行的代码;}…//OtherStatements388.4.1try/catch语句一个异常被抛出后,try语句处理一般分三种情况:⑴try子句内的语句没有发生任何异常,如果没有finally子句,那么跳过catch子句,直接执行try语句后面的语句OtherStatements。⑵try子句内的语句发生异常并被catch子句捕获,将异常对象的引用值传递给catch子句的参数变量,中断现有的流程,跳转到该catch子句,执行异常处理语句。如果catch子句没有产生新的异常对象,执行完catch子句后,如果没有finally子句,就直接执行try语句后面的OtherStatements语句。⑶try子句内的语句发生异常,但是没有被catch子句捕获。398.4.1try/catch语句例8-8classPrimaryAdd{publicdoubleadd(doublea,doubleb){ try{
if(a<0||b<0)thrownewException("a<0||b<0"); }catch(Exceptione){
System.out.println("ishandlingthisExceptionobject.");
} returna+b; }}408.4.1try/catch语句publicclassEx8_8{publicstaticvoidmain(String[]args){
PrimaryAdd
obj=newPrimaryAdd(); System.out.println("2+3="+obj.add(2,3)); System.out.println("-2+3="+obj.add(-2,3));
System.out.println("endofEx8_8");}}程序运行结果:2+3=5.0ishandlingthisExceptionobject.-2+3=1.0endofEx8_8418.4.1try/catch语句例8-9classPrimaryAdd{publicdoubleadd(doublea,doubleb)throwsException{
if(a<0||b<0)thrownewException("a<0||b<0"); }
returna+b; }}428.4.1try/catch语句例8-9publicclassEx8_9{publicstaticvoidmain(String[]args){
PrimaryAdd
obj=newPrimaryAdd();
try{ System.out.println("2+3="+obj.add(2,3)); System.out.println("-2+3="+obj.add(-2,3));
}
catch(Exceptione){
System.out.println("mainishandlingthisExceptionobject.");
}
System.out.println("endofEx8_9");}}438.4.1try/catch语句例8-10【例8-10】在例8-3自定义异常类的基础上,添加代码,处理该异常。classMyExceptionClass
extendsException{doublex;//定义新的成员变量
MyExceptionClass(doublex){
super("输入错误!"+"x="+x+",当x的平方根为负数时引发了自定义异常。");
this.x=x;}publicStringtoString(){
return"MyExceptionClass:输入错误!";}}448.4.1try/catch语句例8-10classSqrtCalculation{voidcalculate(doublex){
try{
if(x<0.0)thrownewMyExceptionClass(x);elseSystem.out.println(Math.sqrt(x));
}catch(MyExceptionClasse){
System.out.println("calculate()ishandlingthisMyExceptionClassobject.");
System.out.println("objectis"+e);
}
}}458.4.1try/catch语句例8-10publicclassEx8_10{publicstaticvoidmain(String[]args){
SqrtCalculation
obj=newSqrtCalculation();obj.calculate(-4);}}程序运行结果:calculate()ishandlingthisMyExceptionClassobject.objectisMyExceptionClass:输入错误!468.4.2多异常的捕获和处理try语句也允许有多个catch子句,每个catch子句可以捕获一种类型的异常。每次执行try语句时,至多只能有一个异常处理代码被执行。catch子句的排列应该是:先特殊,后一般或先子类,后父类,但只捕获一次。即处理子类型异常的catch子句一定要放在处理超类型异常的catch子句之前,否则,处理子类型异常的处理代码就没有机会被执行。478.4.2多异常的捕获和处理classExceptionDemo{publicstaticvoidmain(String[]args){try{
inta=args.length;
System.out.println("a="+a);
intb=42/a;int[]c={1};c[4]=99;}catch(ArithmeticExceptione){//捕获算术运算异常
System.out.println("Divideby0:"+e);}catch(ArrayIndexOutOfBoundsExceptione){
System.out.println("Arrayindexoob:"+e);
}
System.out.println("Aftertry/catchblocks.");}}48命令行没有输入参数,所以args.length=0,进而a=0,引发除零异常。命令行输入任意参数(如“abc”)后的运行结果是:
a=1java.lang.ArrayIndexOutOfBoundsException:4Aftertry/catchblocks.498.5异常处理的进一步讨论8.5.1没有捕获的异常8.5.2catch子句抛出的异常8.5.3构造方法抛出的异常8.5.4finally子句508.5.1没有捕获的异常当try子句发生异常时,如果没有一个catch子句能够捕捉到,则按下列步骤进行处理:⑴由外层try语句处理⑵由调用方法处理⑶由Java虚拟机执行默认程序518.5.2catch子句抛出的异常try子句发生的异常可以由语句中的某个catch子句捕捉处理,但在执行catch子句内的异常处理代码时也可能再抛出新的异常。此时,原先的异常被遗弃,新的异常从try语句抛出并沿着方法调用栈反方向传递。该新异常或者由外层try语句的catch子句捕捉,或者由方法的调用者处理。528.5.3构造方法抛出的异常【例8-15】在例8-4自定义的TimeException类基础上,对构造方法抛出的异常进行异常处理。classTimeExceptionextendsException{privateint
t,m,s;
TimeException(intt,intm,ints){super("时间设置错误!,当出现时分秒["+t+":"+m+":"+s+"]不在范围内时引发了自定义异常TimeException。");
this.t=t;this.m=m;this.s=s;}publicStringtoString(){return"TimeException:时间设置错误!["+t+":"+m+":"+s+"]";}}538.5.3构造方法抛出的异常classMyTime{privateinthour;//0~23privateintminute;//0~59privateintsecond;//0~59publicMyTime(int
h,int
m,ints)throwsTimeException{
if(h<0||h>=24||m<0||m>=60||s<0||s>=60){thrownewTimeException(h,m,s);}hour=h;minute=m;second=s;}}548.5.3构造方法抛出的异常publicclassEx8_15{publicstaticvoidmain(String[]arg){
MyTimet; try{ t=newMyTime(11,69,10); }catch(TimeExceptione){
System.out.println("toString()is"+e.toString());
System.out.println("getMessage()is"+e.getMessage()); }
System.out.println("finish!");}}55程序运行结果:toString()isTimeException:时间设置错误![11:69:10]getMessage()is时间设置错误!,当出现时分秒[11:69:10]不在范围内时引发了自定义异常TimeException。finish!568.5.4finally子句只要离开try语句,都要先执行finally子句。在try语句中,finally子句和catch子句至少出现一个。publicvoidoperateFile(){try{openfile;read/writefile;//可能抛出Exception异常
}catch(Exceptione){handleException;}finally{closefile;}}
578.5.4finally子句控制流离开try语句的情况可分为以下几种:⑴try子句代码正常执行,没有抛出异常;⑵try子句代码执行时抛出异常,但被catch子句捕捉处理;⑶try子句代码执行时抛出异常,但没有catch子句能够捕捉处理;⑷try子句代码执行时抛出异常,且被catch子句捕捉,但在执行异常处理代码时发生新的异常。588.6提高与总结8.6.1异常处理机制和编程方法总结8.6.2银行取款的异常处理8.6.3职员年龄的异常处理598.6.1异常处理机制和编程方法总结Java语言采用面向对象的方法来处理异常。其异常处理机制是:⑴当方法执行过程中出现错误而干扰了程序正常流程时,会抛出一个异常,即构造出一个异常类的对象。⑵异常类对象代表当前出现的一个具体异常,该对象封装了异常的有关信息。608.6.1异常处理机制和编程方法总结⑶Java虚拟机在方法调用栈中寻找能处理该异常的catch子句。它首先检查当前方法是否存在这样的catch子句,如果存在,那么就执行该catch子句;否则,沿方法调用栈中调用顺序的反方向,传递异常对象,寻找能处理该异常的catch子句。如果始终没有这样的catch子句,Java虚拟机打印方法调用栈的异常信息,终止当前线程。该异常处理机制对应的Java语句是:try-catche-finally语句。618.6.2银行取款的异常处理【例8-17】在定义银行类时,若取钱数大于余额则作为异常处理。
classInsufficientFundsExceptionextendsException{privateBankexcepbank;privatedoubleexcepAmount;
InsufficientFundsException(Bank
ba,doubledAmount){
excepbank=ba;
excepAmount=dAmount;}628.6.2银行取款的异常处理publicStringtoString(){Stringstr="Thebalance"+excepbank.getbalance()+",Thewithdrawalwas"+excepAmount;returnstr;}}classBank{doublebalance;//余额
Bank(doubleb){balance=b;}638.6.2银行取款的异常处理publicvoiddeposite(double
dAmount){//存钱
if(dAmount>0.0)balance+=dAmount;}publicvoidwithdrawal(double
dAmount)throwsInsufficientFundsException{if(balance<dAmount){thrownewInsufficientFundsException(this,dAmount);}balance=balance-dAmount;}publicdoublegetbalance(){//获取余额
returnbalance;}}648.6.2银行取款的异常处理publicclassEx8_17{publicstaticvoidmain(String[]args){ try{Bankba=newBank(50);ba.withdrawal(100);
System.out.println("Withdrawalsuccessful!");}catch(Exceptione){
System.out.println(e);}}}65程序运行结果:
Thebalance50.0,Thewithdrawalwas100.0668.6.3职员年龄的异常处理【例8-18】职员年龄异常。当职员的年龄大于60岁或小于18岁时作异常处理。classAgeGreater60ExceptionextendsException{privateEmployeeexcepEmployee;privateint
excepAge;publicAgeGreater60Exception(EmployeeexcepEmployee,int
excepAge){
super(excepEmploye
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论