《Java语言程序设计》课件第5章_第1页
《Java语言程序设计》课件第5章_第2页
《Java语言程序设计》课件第5章_第3页
《Java语言程序设计》课件第5章_第4页
《Java语言程序设计》课件第5章_第5页
已阅读5页,还剩70页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

5.1异常分析及异常类

5.2异常处理

5.3小结

5.4习题

5.1.1一个有问题的程序

什么是异常?先来分析一个程序及其运行结果。

【例5-1】除零异常程序。

publicclassDivideZero{

intx;

publicstaticvoidmain(String[]args){

intresult;

5.1异常分析及异常类

DivideZerok=newDivideZero();

result=35/k.x;

System.out.println("result="+result);

System.out.println("programendsok");

}

}

程序运行结果如图5-1所示。图5-1DivideZero.java的运行结果这个程序在编译时不会出现问题,但是在运行时出现了异常。通过提示信息可以知道,程序中第6行的位置出现了被0除的情况。再仔细考虑一下,原来在创建对象k的时候,其数据成员x被初始化成0,即k.x为0,而除0是非法的。

当程序运行时,会发生不正常的事件阻止事先设计好的程序的执行,这些事件称为异常。当这个程序运行到“35/k.x”时,Java抛出一个异常,该异常表示算术操作不能执行,并且程序自动终止。Java抛出的这个异常为java.lang.ArithmeticException,是一个类。为什么运行结果有错误信息的提示呢?这与Java处理异常的机制有关。当Java抛出异常后,有几件事会随之发生。首先,同Java中其他对象的创建一样,Java将使用new创建异常对象。然后,由于当前的执行路径不能继续下去了,所以该路径被终止,并且弹出对异常对象的引用。此时,异常处理机制接管程序,并开始寻找一个恰当的地方来继续执行程序。这个恰当的地方就是“异常处理程序”,它的任务是将程序从错误状态中恢复,以使程序要么换一种方式运行,要么以原有方式继续运行下去。5.1.2异常类的组织

用面向对象的方法来进行异常处理,首先必须建立异常处理类的层次。在异常处理类层次的最上层有一个单独的类叫做Throwable类,用来表示任何可以作为异常被抛出的类,每个异常类都是Throwable的子类。异常类的层次关系如下:

Throwable对象可分为两种类型(从Throwable继承而得到的类型):Error用来表示编译和系统错误(除特殊情况外,一般不用程序员关心);Exception是可以被抛出的基本类型,在Java类库、用户方法以及运行故障中都可能抛出Exception型异常。所以Java程序员关心的基类型通常是Exception。对于Java异常类的全面了解可以查阅HTML格式的Java文档。异常的基本概念是用名称代表发生的问题,即可以望文知意。但需要指出的是,异常并非全是在java.lang包里定义的。有些异常是用来支持其他的程序包,如util、net和io,这些异常可以通过完整的名称或者从其父类中看出,比如所有的输出/输出异常都是从java.io.IOException继承而来的。同时,Java中异常的数目在持续增加,所使用的第三方类库也可能会有自己的异常。所以对于异常,关键是理解概念以及了解如何使用。

Java异常处理主要通过5个关键字控制:try、catch、throw、throws和finally。try的意思是试一试它所包含的代码段中是否会发生异常;当有异常时,用catch抓住它,并进行相应的处理,使程序不受该异常的影响继续执行下去;在程序中用throw明确引发异常;throws的作用是如果一个方法可以引发异常,而它本身并不对该异常处理,那么它必须将这个异常抛给调用它的方法;finally是无论发不发生异常都要被执行的代码。5.2异常处理5.2.1try/catch语句

1.try块

对于异常处理,Java语言提供默认的处理方式。但使用此方式,一旦程序发生异常,程序就会终止运行并显示一些信息,这样用户界面就不很友好。为了避免程序运行时可能出现的错误,将这些程序代码放在try块中,在这个块里“尝试”各种(可能产生异常的)方法调用,用来捕获异常,所以称其为try块。try块是跟在try关键字之后的普通程序块:

try{

//可能抛出异常的代码

}

2.catch块

当然,抛出的异常必须在某处得到处理。这个“某处”就是“异常处理程序”,而且针对每个要捕获的异常,得准备相应的处理程序。所以,紧跟在try语句后面设计了catch语句,用来指定需要捕捉的异常类型,形式如下:

try{

//可能抛出异常的代码

}catch(Type1id1){//处理捕获的第一类异常

}catch(Type2id2){

//处理捕获的第二类异常

}catch(Type3id3){

//处理捕获的第三类异常

}

//等等

catch子句(异常处理程序)就像是只接受一个特殊类型的参数的方法。异常处理程序必须紧跟在try块之后,一旦出现异常情况,程序抛出一个异常并终止try程序的运行,异常处理机制将负责搜寻参数与异常类型相匹配的第一个处理程序。然后进入catch子句执行,此时认为异常得到了处理。一旦catch子句结束,则处理程序的查找过程结束。需要注意的是,只有匹配的catch子句才能得到执行。

现在针对DivideZero.java程序做几种处理,分析运行结果,深入理解try/catch的处理机制。【例5-2】没有cathch语句的程序。

publicclassDivideZero_Handle1{

intx;

publicstaticvoidmain(String[]args){

intresult;

DivideZero_Handle1k=newDivideZero_Handle1();try{

result=35/k.x;

System.out.println("result="+result);

}

System.out.println("programendsok!");

}

}

程序编译结果如图5-2所示。图5-2DivideZero_Handle1.java的编译结果【例5-3】只有一条cathch语句的程序。

publicclassDivideZero_Handle2{

intx;

publicstaticvoidmain(String[]args){

intresult;

DivideZero_Handle2k=newDivideZero_Handle2();

try{

result=35/k.x;System.out.println("result="+result);

}

catch(Exceptione){//捕获异常

System.out.println("errorsoccur!");

}

System.out.println("programendsok!");

}

}

程序运行结果如图5-3所示。图5-3DivideZero_Handle2.java的运行结果【例5-4】显示异常类对象的相关信息。

publicclassDivideZero_Handle3{

intx;

publicstaticvoidmain(String[]args){

intresult;

DivideZero_Handle3k=newDivideZero_Handle3();

try{

result=35/k.x;

System.out.println("result="+result);

}

catch(Exceptione){//将堆栈轨迹输出到标准错误流

e.printStackTrace();

//得到这个对象的错误消息字符串

System.out.println("getmessage="+e.getMessage());

//得到这个对象的短说明

System.out.println("tostring="+e.toString());

}

System.out.println("programendsok!");

}

}

程序运行结果如图5-4所示。图5-4DivideZero_Handle3.java的运行结果

catch的参数e为Exception类型,它继承了Throwable类。该类中有多个方法可以得到对象e的异常信息。

【例5-5】有多条catch语句的程序。

publicclassDivideZero_Handle4{

intx;

publicstaticvoidmain(String[]args){

intresult;

DivideZero_Handle4k=newDivideZero_Handle4();

try{result=35/k.x;

System.out.println("result="+result);

}

catch(ArrayStoreExceptione){//第1条catch语句

System.out.println("数组下标越界.");

}

catch(ArithmeticExceptione){//第2条catch语句

System.out.println("出现被0除的异常情况.");}

catch(Exceptione){//第3条catch语句

System.out.println("检查除数的有效性.");

}

System.out.println("programendsok!");

}

}

程序运行结果如图5-5所示。图5-5DivideZero_Handle4.java的运行结果异常处理机制从多个catch子句中搜寻到参数与异常类型(ArithmeticException)相匹配的第一个处理程序,然后进入catch子句执行处理程序,处理完后,跳出try/catch块,继续执行程序。

实际上ArithmeticException异常类是Exception类的子类,如果将第二个catch语句屏蔽掉,异常处理机制就会顺次找到第三个catch子句并执行,情况与例5-4相同。程序运行结果如图5-6所示。图5-6屏蔽了第二个catch子句后的运行结果5.2.2throw/throws语句

1.throw语句

如果在执行一段代码时,需要程序进行其他处理,就可以借助于异常,使程序执行指定的操作。产生异常又称为抛出异常,如果要故意抛出ClassCastException异常(类强制转换异常),那么可以在try中增加下面的语句:

thrownewClassCastException();关键字throw的意思就是“抛出”,newClassCastException()就是创建了一个ClassCastException类的对象。

下面这个程序用来计算一个非负整数的平方根。

【例5-6】ThrowDemo.java程序。

publicclassThrowDemo{

intx;

publicThrowDemo(inttemp){

x=temp;

}

publicstaticvoidmain(String[]args){

ThrowDemok=newThrowDemo(-15);

try{

if(k.x<0)

thrownewException("需要计算的数必须是一个非负整数!");

else

System.out.println("sqrt("+k.x+")="+Math.sqrt(k.x));}

catch(Exceptione){

System.out.println("GotaException:"+e.getMessage());

}

}

}

程序运行结果如图5-7所示。图5-7ThrowDemo.java的运行结果

2.throws语句

在ThrowDemo.java程序中,异常抛出后,是在异常被抛出的方法(main方法)中进行处理的。如果抛出的异常由调用它的方法完成处理该如何做?这时需要把异常从产生异常的方法中抛出,即利用throws关键字进行处理。假设将平方根的计算用sqrt方法进行设计,把异常从方法中抛出的程序是:

publicvoidsqrt()throwsException{

//求平方根的程序代码

}

在方法的声明中加上throwsException,就可以把sqrt方法中产生的异常抛出方法之外,留给调用它的其他方法(main方法)去处理。【例5-7】利用throws语句处理ThrowDemo.java程序。

publicclassThrowsDemo_1{

intx;

publicThrowsDemo_1(inttemp){

x=temp;

}

publicvoidsqrt()throwsException{//方法声明中抛出可能出现的异常

if(x<0)

thrownewException("需要计算的数必须是一个非负整数!");

elseSystem.out.println("sqrt("+x+")="+Math.sqrt(x));

}

publicstaticvoidmain(String[]args){

ThrowsDemo_1k=newThrowsDemo_1(-15);

try{

k.sqrt();}

catch(Exceptione){

System.out.println("Caughtinsidemain_method:"+e.getMessage());

}

}

}

程序运行结果如图5-8所示。图5-8ThrowsDemo_1.java的运行结果为了更好地理解throw和throws的用法,请阅读和分析下面这个例题。

【例5-8】利用throw和throws语句进行非负整数的平方根计算。

publicclassThrowsDemo_2{

intx;

publicThrowsDemo_2(inttemp){

x=temp;

}

publicvoidsqrt()throwsException{

try{

if(x<0)

thrownewException("需要计算的数必须是一个非负整数!");

else

System.out.println("sqrt("+x+")="+Math.sqrt(x));

}

catch(Exceptione){//捕获try语句中抛出的异常System.out.println("Caughtinsidesqrt_method:"+e.getMessage());

throwe;//抛出异常对象e,交给上一级方法—main

}

}

publicstaticvoidmain(String[]args){

ThrowsDemo_2k=newThrowsDemo_2(-15);

try{k.sqrt();

}

catch(Exceptione){//捕获sqrt方法抛出的异常

System.out.println("Caughtinsidemain_method:"+e.getMessage());

}

}

}

程序运行结果如图5-9所示。图5-9ThrowsDemo_2.java的运行结果通过这个例题的演示,throw和throws的概念更加明显:

(1) throw出现在方法体中,用于抛出异常。当方法在执行过程中遇到异常情况时,程序将异常信息封装为异常对象,然后throw。

(2) throws出现在方法的声明中,表示该方法可能会抛出的异常,允许throws后面跟着多个异常类型。5.2.3finally语句

如果希望无论try块中的异常是否抛出,程序都能执行一段代码,Java提供了另一种处理块的语法,即finally关键字。

finally语句创建一个代码块,在try/catch语句后执行,不管是否抛出异常,系统都将执行finally语句的程序代码。所以完整的异常处理应该如下面的形式:

try{

//可能抛出异常A、BorC

}catch(Aa1{//处理异常情况A

}catch(Bb1){

//处理异常情况B

}catch(Cc1){

//处理异常情况C

}finally{

//任何情况都必须执行的代码

}

【例5-9】程序FinallyTest.java对finally的使用情况作了测试。

publicclassFinallyTest{

intx;

publicFinallyTest(inttemp){

x=temp;

}publicstaticvoidmain(String[]args){

FinallyTestk=newFinallyTest(-15);

try{

if(k.x<0)

thrownewException("需要计算的数必须是一个非负整数!");

else

System.out.println("sqrt("+k.x+")="+Math.sqrt(k.x));

}catch(Exceptione){

System.out.println("GotaException:"+e.getMessage());

}

finally{

System.out.println("被求平方根的数是:"+k.x);

}

}

}

程序运行结果如图5-10所示。图5-10FinallyTest.java的运行结果如果将-15改成16,程序的运行结果如图5-11所示。

从两个输出结果中发现,无论异常是否被抛出,finally子句总能被执行。使用finally语句可为异常处理提供统一的出口,一般来说可以在finally语句中进行资源清除工作,如关闭已打开的文件等。图5-11对16求平方根的运行结果5.2.4自定义异常

Java提供的异常体系不可能预见所有可能出现的错误。在实际应用中,可以自己定义异常类来表示程序中可能会遇到的特定问题。

如果要建立自己的异常类,必须从已有的异常类继承。根据前面的知识,异常处理类的顶层类是Throwable,但是Java程序员关心的基类型通常是它的子类Exception。所以可以通过继承Exception类来创建自己的异常类,即只需提供一个构造方法并覆盖要使用的方法即可。表5-1列出了Throwable类的构造函数。表5-1Throwable类的构造函数下面建立的是一个最简单的异常类:

classSimpleExceptionextendsException{}

这个异常类让编译器产生了缺省的构造方法,它将自动调用基类的缺省构造器。

【例5-10】创建自定义异常类,完成输入温度的检测报告。如果温度高于75度,显示不正常,否则均为正常。

classNewExceptionextendsException{

//创建自定义异常类

intvalue;

//带参数的构造方法的定义

NewException(inttemp){

value=temp;

}

publicStringtoString(){

//覆盖了父类方法toString(),使对象具有自己的显示信息

return"NewException"+value+"度";}

}

publicclassTemperatureForecast{

staticvoidforecast(intvalue)throwsNewException{

//温度检测

if(value>75)

thrownewNewException(value);

else

System.out.println(value+"度:Noproblem.");

}publicstaticvoidmain(String[]args){

try{//检测三个温度

forecast(60);

forecast(55);

forecast(95);

}

catch(NewExceptione){//处理forecast方法中抛出的异常

System.out.println(e+":HigherTemperature!");

}

}

}

程序运行结果如图5-12所示。图5-12TemperatureForecast.java的运行结果

【例5-11】创建自定义异常类,完成对银行账目的操作处理。

类BankAccount维持银行账目的余额:

(1)它有两个构造方法:①用空的余额创建一个新的银行账户;②用正的余额创建一个新的银行账户;

(2)提供三个实例方法支持余额的访问和操作:①返回该银行账户的余额;②向该银行账户中存入正值的数额;③从该银行账户中取出正值的数额。程序清单如下:

//创建自定义异常类,表示一个不正常的银行账目事件

classNegativeAmountExceptionextendsException{

//用消息s创建异常

publicNegativeAmountException(Strings){

super(s); //调用基类构造器,接受一个字符串作为参数

}

}//表示银行账目余额

classBankAccount{

intbalance;

//默认的构造方法,余额为空

publicBankAccount(){

balance=0;

}//特定的构造方法,余额为n

publicBankAccount(intn)throwsNegativeAmountException{

if(n>=0)

balance=n;

else

thrownewNegativeAmountException("Badbalance.");

}//返回当前的余额

publicintgetBanlance(){

returnbalance;

}

//存款:数额为n

publicvoidaddFunds(intn)throwsNegativeAmountException{

if(n>=0)

balance+=n;

elsethrownewNegativeAmountException("Badbalance.");

}

//取款:数额为n

publicvoidremoveFunds(intn)throwsNegativeAmountException{

if(n<0)

thrownewNegativeAmountException("Badbalance.");

elseif(balance<n)

thrownewNegativeAmountException("Badbalance.");

else

balance-=n;}

}

//进行业务操作

publicclassDeposits{

publicstaticvoidmain(String[]args){

try{

BankAccountk1=newBankAccount(500);

//向k1里存500

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论