ch06.docx

上传人:b****8 文档编号:9386651 上传时间:2023-02-04 格式:DOCX 页数:21 大小:123.76KB
下载 相关 举报
ch06.docx_第1页
第1页 / 共21页
ch06.docx_第2页
第2页 / 共21页
ch06.docx_第3页
第3页 / 共21页
ch06.docx_第4页
第4页 / 共21页
ch06.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

ch06.docx

《ch06.docx》由会员分享,可在线阅读,更多相关《ch06.docx(21页珍藏版)》请在冰豆网上搜索。

ch06.docx

ch06

第6章Java异常处理

任何一个软件在运行中都会出现故障,在故障出现后需要有较为及时且有效的处理办法。

Java语言的异常处理机制是由捕获异常和处理异常两部分组成的。

本章主要介绍Java语言的异常处理机制。

本章要点

●异常和异常分类

●Java异常处理机制

●自定义异常

本章难点

●Java异常处理机制

学习目标

●理解Java异常处理机制。

●了解自定义异常。

6.1异常处理概述

6.1.1异常及其分类

任何计算机语言的程序都难免有漏洞,捕获错误最理想的是在编译期间,然而,在实际的程序设计中,并非所有错误都能在编译期间侦测到。

例如,下列情况在编译时通常检测不到:

类文件丢失、想打开的文件不存在、网络连接中断、操作数超出预定范围等。

这些在程序执行中,中断正常程序流程的异常条件称为错误或异常。

Java中,所有的异常都由类来表示。

所有的异常类都是从一个名为Throwable的类派生出来的。

因此,当程序中发生一个异常时,就会生成一个异常类的某种类型的对象。

Throwable有两个直接子类:

Error和Exception。

Error类表示程序运行时发生的严重错误,Exception类表示程序运行时产生的异常。

Error和Exception类又派生了很多子类用来表示程序运行产生的具体错误和异常。

例如使用NoClassDeFormatError表示没有类定义所产生的错误,使用ArithmeticException类表示算术运算产生的异常等。

Java中异常及其类的层次结构如图6-1所示:

图6-1异常类的层次结构

异常类Exception的构造函数及常用方法:

①Exception()

建立一个没有详细信息的异常。

②Exception(Strings)

建立一个有详细信息的异常,当异常被捕获时,可以从信息当中得知错误发生的原因。

③获得异常的有关信息

publicStringtoString():

返回描述异常类信息的字符串。

publicvoidprintStackTrace():

在当前标准输出当前异常对象的堆栈使用轨迹。

publicStringgetMessage():

输出错误的信息。

6.1.2异常处理机制

程序运行所导致的异常发生后,由Java语言提供的异常处理机制处理,Java异常处理机制由捕获异常和处理异常两部分组成。

在Java程序的执行过程中,如果出现了异常事件,就会生成一个异常对象。

生成的异常对象将传递给Java运行时系统,这一异常的产生和提交过程称为抛出(throw)异常。

当Java运行时系统得到一个异常对象时,它将会寻找处理这一异常的代码。

找到能够处理这种类型的异常的方法后,运行时系统把当前异常对象交给这个方法进行处理,这一过程称为捕获(catch)异常。

如果Java运行时系统找不到可以捕获异常的方法,则运行时系统将终止,相应的Java程序也将退出。

6.1.3Java中的常用异常类

1.执行异常

执行异常即运行时异常,继承于RuntimeException。

Java编译器允许程序不对它们做出处理。

下面列出了主要的运行时异常:

ArithmeticException:

一个不寻常算术运算产生的异常。

ArrayIndexOutOfBoundsException:

数组索引超出范围所产生的异常。

ClassCastExcption:

类对象强迫转换造成不当类对象所产生的异常。

NumberFormatException:

字符串转换数值所产生的异常。

IndexOutOfBoundsException:

索引超出范围所产生的异常。

NegativeException:

数组建立负值索引所产生的异常。

NullPointerException:

对象引用参考值为null所产生的异常。

2.检查异常

除了执行异常外,其余的Exception子类属于检查异常类,也称为非运行时异常。

Java编译器要求程序必须捕获或者声明抛出这种异常。

下面列出了主要的检查异常:

ClassNotFoundException:

找不到类或接口所产生的异常。

IllegaAccessException:

类定义不明确所产生的异常。

InterruptedException:

目前线程等待执行,另一线程中断目前线程所产生的异常。

【例6_1】ArithmeticException异常抛出示例

publicclassExam6_1{

publicstaticvoidmain(String[]args){

inti=10/0;

System.out.println(i);

}

}

程序运行时,由于使用10/0对i进行附值,除数为零,从而抛出算术异常,即ArithmeticException类的异常对象。

程序结果如图6-2所示。

图6-2例6_1程序运行结果

6.2Java异常的处理方法

为了写出健壮的Java程序,当程序出现异常时就应当进行处理,Java程序对异常处理有两种方式:

①通过try{}catch(){}finally{}块处理异常。

把可能会发生异常的程序代码放在try区块中,那么当程序执行发生异常时,catch区块会捕捉这个异常,并且以区块内的程序代码来处理异常,而finally区块则负责处理一些必要的工作,请注意,无论try区块内的程序代码是否发生异常finally区块内的程序代码都会被执行。

②将异常抛给上一层调用它的方法,由上一层方法进行异常处理或继续向更上一层方法抛出该异常。

6.2.1try/catch/finally

1.try/catch

异常处理的核心是try和catch。

这两个关键字要一起使用,只有try而没有catch,或者只有catch而没有try都是不可以的。

下面是try/catch异常处理代码块的基本形式:

try//监视

{

可能发生异常的代码块;

}

catch(异常类型异常对象名)//捕获并处理异常

{

异常处理代码块;

}

当try描述的代码段遇到异常发生时,会抛出一个异常对象,该异常由相应的catch语句捕获并处理。

与一个try相关的catch语句可以有多个,构成多重catch语句,异常类型决定了要执行哪个catch语句。

也就是说,如果由一个catch语句指定的异常类型与发生的异常类型相符,那么就会执行这个catch语句(其他的catch语句则被跳过)。

如果catch语句执行完毕或者没有抛出异常,就会执行最后一个catch后面的第一个语句。

【例6_2】使用异常处理的例子。

publicclassExam6_2{

publicstaticvoidmain(String[]args){

try{

device(Integer.parseInt(args[0]));

}catch(ArithmeticExceptione){

System.out.println("输入为零,产生异常,被catch捕获到");

}

System.out.println("输入不为零,没有产生异常!

");

}

staticintdevice(inti){

return10/i;

}

}

程序中用户输入的值与10做除法,当用户输入的数值不为零时,程序不会抛出异常,执行结果如图6-2所示,当用户输入零时,程序抛出异常,并被catch语句捕获后处理,程序执行结果如图6-3所示。

图6-2例6_2输入不为0时程序运行结果

图6-3例6_2输入为0时程序运行结果

2.使用多重catch语句

与一个try相关的catch语句可以有多个,每一个catch语句捕获一个不同类型的异常。

当异常发生时,每一个catch子句被依次检查,第一个匹配异常类型的子句被执行。

一个catch语句执行以后,其他的子句被忽略,程序从try/catch块后的代码开始继续执行。

其形式如下所示:

try

{

可能发生异常的代码块;

}

catch(异常类型1异常对象名1)

{

异常处理代码块1;

}

catch(异常类型n异常对象名n)

{

异常处理代码块n;

}

【例6_3】捕获两种不同类型的异常。

publicclassExam6_3

{

publicstaticvoidmain(Stringargs[])

{

try

{

inti=args.length;

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

intj=5/i;

intk[]={1,2,3};

k[5]=0;

}

catch(ArithmeticExceptione)

{

System.out.println("被零除:

"+e);

}

catch(ArrayIndexOutOfBoundsExceptione)

{

System.out.println("Arrayindexoutofboundexception:

"+e);

}

System.out.println("执行catch块后的语句块");

}

}

当程序执行不输入任何命令行参数时,数组args[]的长度为空,此时i为0,运行结果如图6-4所示。

图6-4例6_3程序执行不输入命令行参数

 

输入命令行参数后,数据的长度大于0,i的值不为0。

程序运行结果如图6-5所示。

图6-5例6_3程序输入命令行参数后结果

两次运行的不同输出结果证实,每一个语句只对自己的异常类型做反应。

总之,catch表达式按照在程序中的顺序被检查。

只执行匹配的语句,忽略其他所有catch代码块。

3.finally关键字的使用

有时需要在catch处理异常后进行一些其他的操作,比如关闭一个已经打开了的文件,此时,可以在try/catch代码块的后面加上finally代码段来处理这种情况。

try/catch/finally的基本形式如下所示:

try

{

可能发生异常的代码块;

}

catch(异常类型异常对象名)

{

异常处理代码块;

}

finally

{

无论是否抛出异常都要执行的代码;

}

【例6_4】使用finally的示例。

publicclassExam6_4{

publicstaticvoidmain(String[]args){

try{

device(Integer.parseInt(args[0]));

}catch(ArithmeticExceptione){

System.out.println("输入为零,产生异常,被catch捕获到");

}

finally{

System.out.println("不论有没有产生异常,都会被执行的代码段!

");

}

}

staticintdevice(inti){

return10/i;

}

}

当命令行参数输入为0即产生异常时,该程序运行结果如图6-6所示,当命令行参数输入不为0即无异常时,程序运行结果如图6-7所示。

图6-6例6_4程序产生异常时运行结果

图6-7例6_4程序无异常时运行结果

一般地来说,finally程序块中的代码完成一些资源释放、清理的工作。

如,关闭try程序块中所有打开的文件,断开网络连接,使用getMessage()方法返回保存在某个异常中的描述字符串,使用PrintStackTrace()方法把调用堆栈的内容打印出来,等等。

6.2.2throws

有些时候不方便立即对出现的异常进行处理,Java提供了另一种处理异常的方式,将出现的异常向调用它的上一层方法抛出,由上层方法进行异常处理或继续向上一层方法抛出该异常。

在这种情况下,可以使用throws子句标记方法的声明,表明该方法不对抛出的异常进行处理,而是向调用它的方法抛出该异常。

thorws语句的使用格式如下:

[修饰符]返回类型方法名(参数1,参数2,……)throws异常列表

{……}

例如:

publicintread()throwsException

{……}

publicstaticvoidmain(Stringargs[])throwsIOException,IndexOutOfBoundsException

{……}

【例6_5】throws使用示例。

publicclassExam6_5{

publicstaticvoidmain(String[]args){

try{

device();

}catch(ArithmeticExceptione){

System.out.println("main()方法捕获到device()方法产生的异常并进行处理");

}

}

staticintdevice()throwsArithmeticException{

return10/0;

}

}

程序中的device方法中使用零做除数,会抛出异常。

但方法本身,并没有对该异常进行处理,而是抛给了调用它的main()方法进行处理,程序执行结果如图6-8所示。

图6-8例6_5程序运行结果

6.2.3抛出异常(throw)

前面的例子中所涉及的异常都是由Java虚拟机(JVM)自动产生的,如果想在某些语句中手动抛出异常对象,则可以是通过throw语句实现的,但其基本形式如下:

thrownew异常名();

【例6_6】使用throw关键字手动抛出IOException异常。

publicclassExam6_6{

publicstaticvoidmain(String[]args){

try{

device(Integer.parseInt(args[0]));

}catch(ArithmeticExceptione){

e.printStackTrace();

}

}

staticvoiddevice(inti)throwsArithmeticException{

if(i==0)thrownewArithmeticException("输入为零,请重新输入!

");

else

System.out.println("10/"+i+"="+10/i);

}

}

程序中若输入非零值,则输出10与该值的除法结果,如图6-9所示。

若输入零值,则由throw语句抛出异常,并在main()方法中捕获,使用printStackTrace()方法输出错误信息,如图6-10所示。

图6-9例6_6程序无异常时运行结果

图6-10例6_6程序产生异常时运行结果

6.2.4自定义Java异常

尽管Java的内置异常能够处理大多数常见错误,但有时还可能出现系统没有考虑到的异常,此时我们可以自己建立异常类型,来处理所遇到的特殊情况。

只要定义Exception的一个子类就可以建立自己的异常类型。

自定义异常的基本形式如下所示:

class自定义异常extends父异常类名

{

类体;

}

【例6_7】自定义异常示例。

publicclassExam6_7extendsException{

Exam6_7(){

System.out.println("输入为零,请重新输入!

");

}

}

classTest{

publicstaticvoidmain(String[]args){

try{if(args[0].equals("0"))

{

thrownewExam6_7();

}

else

{

System.out.println("10/"+args[0]+"="+10/Integer.parseInt(args[0]));

}}

catch(Exceptione){

}

}

}

程序首先创建了Exception的子类Ecam6_7,即创建了一个异常对象,然后在Test类中抛出了该异常对象,程序运行结果如图6-11所示。

图6-11例6-7产生异常时程序运行结果

6.3案例—异常实例

在本节中,我们编写一个程序对用户输入的电话号码格式进行判断,并对可能出现的异常进行抛出、使用自定义的异常进行处理。

电话号码只能是数字,且要有一定的位数。

为简单起见,我们不考虑区号,则0不能打头。

用户的输入可能正确,也可能错误,甚至忘记输入。

这一切都可以通过异常来判断,且将这些进行自定义异常会有更有好的用户界面。

我们可以通过下面的程序实现上述要求。

classTelephoneException{

staticStringtelephone;

publicstaticvoidmain(String[]args){

try{

telephone=args[0];

if(istelephone(telephone)){

System.out.println("电话号码格式输入正确!

");

}

else{

System.out.println("电话号码格式输入不正确!

");

}

}

catch(ArrayIndexOutOfBoundsExceptione){

System.out.println("没有输入电话号码!

");

}

catch(MyExceptione){

System.out.println(e.getMessage());

}

}

publicstaticbooleanistelephone(Stringtelephone)throwsMyException{

booleanistelephone=true;

if(telephone.length()!

=8){

thrownewMyException("电话号码位数不对!

");

}

try{Integer.parseInt(telephone);}

catch(NumberFormatExceptione){

thrownewMyException("不能输入数字以外的符号!

");

}

if(telephone.charAt(0)=='0'){

thrownewMyException("0不能打头!

");

}

returnistelephone;

}

}

classMyExceptionextendsException{

MyException(Stringmessage){

super(message);

}

}

在这个程序中,我们主要是通过方法istelephone()来判断用户的输入是否是正确的电话号码格式,如果用户输入格式正确,则该方法返回boolean值true,否则返回false。

在方法istelephone()中,我们通过length()方法来判断电话号码的位数是否为8位,通过将其转换成整形值来判断是否只输入了数字,通过获得首字符来判断是否首字符为0,出现上面任何一种情况,我们都在程序中抛出自定义的异常类MyException类的对象。

而在主程序中我们通过判断命令行参数的长度,来确定用户是否输入了数据。

程序的运行结果如图6-12到6-15所示。

图6-12程序TelephoneException输入位数错误时运行结果

图6-13程序TelephoneException输入符号错误时运行结果

图6-14程序TelephoneException首位错误时运行结果

图6-15程序TelephoneException输入正确时运行结果

小 结

Java中异常类具有层次组织。

其中Throwable类是Error类和Exception类的父类,是Object的直接子类。

异常类(java.lang.Exception)继承于java.lang.Object中的java.lang.Throwable类。

Java语言的异常处理机制是由捕获异常和处理异常两部分组成的。

捕获异常和处理异常可以格式化地的表示为:

try{

可能发生异常的代码块;

}

catch(异常类型1异常对象名1){

异常处理代码块1;

}

catch(异常类型n异常对象名n){

异常处理代码块n;

}

finally{

无论是否抛出异常都要执行的代码;

}

异常处理模块可以嵌套,可以使用throws和throw关键字主动抛出异常,其基本格式为:

[修饰符]返回类型方法名(参数1,参数2,……)throws自定义异常

{

thrownew(异常类);

}

也可以创建自定义异常类,其格式为:

class自定义异常extends父异常类名

{类体;}

实训6

一、实训目的

1.熟悉异常处理方法。

2.熟悉常见异常的捕获方法。

3.了解自定义异常。

二、实训内容

通过继承Exception类来实现自己的异常类。

并使用try-catch来捕获这个异常。

习题6

一.填空题

1.Java语言的异常处理机制是由___________和___________两部分组成的。

2.所有的异常类都是从一个名为__________的类派生出来的。

因此,当程序中发生一个异常时,就会生成一个异常类的某种类型的__________。

3.ava语言提供的异常处理机制,由___________和___________两部分组成。

4.Java程序在进行异常处理时把可能会发生异常的程序代码放在__________区块中,那么当程序执行发生异常时,__________区块会捕捉这个异常,并且以区块内的程序代码来处理异常,而__________区块则负责处理一些必要的工作。

5.Java提供了另一种处理异常的方式,将出现的异常向调用它的上一层方法抛出,由上层方法进行异常处理或继续向上一层方法抛出该异常。

在这种情况下,可以使用__________子句标记方法的声明,表明该方法不对抛出的异常进行处理,而是向__________抛出该异常。

二.判断题

1.(  )Java中,所有的异常都由类来表示。

2.(  )Exception类表示程序运行时发生的严重错误,Error类表示程序运行时产生的异常。

3.(  )生成的异常对象将传递给Java运行时系统,这一异常的产生和提交过程称为抛弃(throw)异常。

4.(  )异常处理的核心是try和catch,这两个关键字可以分开使用。

5.(  )当try描述的代码段遇到异常发生时,会抛出一个异常对象,该异常由相应的catch语句捕获并处理。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 小学教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1