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

下载本文档

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

文档简介

第6章异常处理6.1异常的概念6.2Java语言异常的处理6.3异常的类型

6.1异 常 的 概 念

6.1.1案例:异常处理方法演示

程序在执行过程中可能会发生多种严重程度不同的错误,这些错误与编译错误不同,不是程序语法的错误,而是由运行时遇到的一些特殊情况引起的。例如,由于网络的问题不能正常从网络服务器获取数据。程序运行时发生错误,Java语言称之为异常,它会使程序的运行流程发生改变。对于异常可以采取多种方式进行处理,如终止程序运行,这是最简单的方法。当然,大多数情况下用户不希望采取这种处理方法。当发生错误时,用户一般会希望程序能够给出足够的错误信息,继续运行。因此,一个好的程序员在编写程序时,必须预测程序执行过程中可能发生的各种异常情况。Java语言提供了一种不同于传统程序设计语言的异常处理方法,使程序员可以方便地检测和处理各种异常情况。下面先看一个例子。【程序6.1】异常处理方法演示。

publicclassExceptionDemo

{

staticint[]IntArrayAdd(int[]a,int[]b)

{

int[]c=newint[a.length];

for(inti=0;i<c.length;i++)

c[i]=a[i]+b[i];

returnc;

}

publicstaticvoidmain(String[]args) {

int[]a=newint[20];

int[]b=newint[10];

for(inti=0;i<20;i++)

a[i]=i;

for(inti=0;i<10;i++)

b[i]=i;

try{

int[]c=IntArrayAdd(a,b);

for(inti=0;i<c.length;i++)

System.out.print(""+c[i]);

}catch(Exceptione){

System.out.println(“Thereisanerror!”);

}

}

}

程序运行结果为

Thereisanerror!

从第3章有关数组的知识可以知道,程序6.1的main方法在调用方法IntArrayAdd对数组b访问时下标超界,产生一个异常。由于程序6.1采用了Java语言中的异常处理方法,程序执行流程发生变化,转到语句System.out.println("Thereisanerror!")执行。6.1.2异常处理

传统的程序设计语言(例如C)需要程序员检测错误发生的原因并进行处理,这样,就需要在正常执行流程中增加一些if-else语句或switch-case语句来检测函数的返回值或全局的错误代码,判断发生了什么类型的错误。这种处理方法使得程序的流程变得复杂,难以阅读理解,而Java语言的异常处理机制使得错误信息的处理和流程控制变得很简单。观察一下程序6.1可以发现,程序中的错误在IntArrayAdd方法中发生,但是该方法中并没有错误处理语句,既没有用返回值标志错误发生,也没有设置一个main方法和IntArrayAdd方法可以共同访问的变量用于传递错误信息。那么,错误信息是怎样从IntArrayAdd方法传递到main方法的呢?

实际上IntArrayAdd方法在超界访问数组元素时抛掷了一个异常,创建了一个异常对象用于存储错误信息,由于IntArrayAdd方法没有处理该异常,Java虚拟机终止IntArrayAdd方法的执行,然后自动返回到main方法,将流程转入异常处理部分。与传统的错误处理方法相比,Java语言的异常处理机制有很多优点。它将错误处理代码从常规代码中分离出来,例如程序6.1的main方法中先调用IntArrayAdd方法然后输出结果,中间并没有插入错误处理的代码,而按照传统的方法程序的结构应该是这样的:

调用IntArrayAdd方法

if(发生错误)

输出错误信息

else

输出结果当错误类型较多,需要分别处理时,采用这种方法很显然会使程序流程变得十分复杂。

异常处理机制带来的另一个好处是错误的传播,Java异常会自动在方法调用堆栈中传播,例如程序6.1异常从IntArrayAdd方法自动传递到main方法。

另外,Java异常处理机制克服了传统方法的错误信息有限的问题,可以针对不同的错误类型定义不同的异常类,异常处理机制会根据异常对象的类型寻找匹配的错误处理代码。

6.2Java语言异常的处理

6.2.1try-catch块

Java语言中异常的捕捉是通过try-catch块来实现的,其语法形式为

try{

//程序正常的流程,有可能抛掷异常

}

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

//错误的处理

}

finally{

//如果try部分代码执行完或catch部分代码执行完,则执行该部分代码

}

try块为程序正常的流程,如果发生异常,则终止try块的执行转入catch块。对于一个try块,可以有多个catch块,每个catch后的异常类名应不同,Java语言根据异常对象的类型从上向下匹配,执行第一个与之匹配的catch块。

Java语言中所有的异常类都是Throwable类的子类,用户可以从已有的异常类派生新的类型,用于处理用户程序中特有的错误类型。如果找不到匹配的catch块,则该异常继续在调用堆栈中传播,传递给调用该方法的方法。

由于可以将一个派生类对象看成是一个超类的对象,因此,如果多个catch块后的异常类有继承关系,则应将派生类放在前面。例如,当程序中数组下标超界时,Java抛掷出ArrayIndexOutOfBoundsExeption类的异常对象,该异常类是Exception的派生类,因此应将ArrayIndexOutOfBounds

Exeption异常类的catch块放在前面。例如下面的程序段:inta[]=newint[10];

try{

for(inti=0;i<=10;i++)

a[i]=i;

}catch(ArrayIndexOutOfBoundsExeptione){

System.out.println("ArrayIndexoutofBounds");

}catch(Exceptione){

System.out.println("Thereisanexception");

}

该程序段将输出:

ArrayIndexoutofBounds而如果将两个catch块的顺序对调,则变成下面的形式:

inta[]=newint[10];

try{

for(inti=0;i<=10;i++)

a[i]=i;

}catch(Exceptione){

System.out.println("Thereisanexception");

}

catch(ArrayIndexOutOfBoundsExeptione){

System.out.println("ArrayIndexoutofBounds");

}将执行第一个catch块,输出:

Thereisanexception

catch块中的异常对象名相当于方法中的形式参数,作用范围为该catch块,它是对捕捉到的异常对象的引用,可以通过它获得有关错误信息。

finally块对于try-catch块是可选的,当try部分的代码正常执行完或发生异常由某个catch块捕获进行处理后执行其中的代码。如果没有匹配的catch,则发生异常后直接执行finally部分的语句。finally语句不被执行的唯一情况是在try块内执行终止程序的System.exit()方法。【程序6.2】异常处理的执行顺序。

publicclassFinallyBlock

{

publicstaticvoidmain(String[]args)

{

inti=0;

Stringgreetings[]={

"Helloworld!",

"No,Imeanit!",

"HELLOWORLD!!"

}; while(i<4){

try{

System.out.println(greetings[i]);

}catch(ArrayIndexOutOfBoundsExceptione){

System.out.println("Re-settingIndexValue");

i=-1;

}finally{

System.out.println("Thisisalwaysprinted");

} i++;

}

}

}

程序运行时重复输出下面的内容,可按Ctrl+C键终止:

Helloworld!

Thisisalwaysprinted

No,Imeanit!

Thisisalwaysprinted

HELLOWORLD!!

Thisisalwaysprinted

Re-settingIndexValue

Thisisalwaysprinted6.2.2异常的抛掷

异常的抛掷是由throw语句来实现的,如果程序中检测到一个错误,可以创建一个异常对象,然后使用throw抛掷。例如:

thrownewException();

该语句直接调用Exception类的构造方法创建一个Exception类的对象并抛掷该对象。Exception类从Throwable类派生而来,含有两个构造方法:

● publicException();

● publicException(Stringmsg)。根据错误类型的不同,创建的异常对象的类型也不相同。

如果一个方法成员有可能抛掷异常,应在定义该方法成员时使用throws关键字声明其可能抛掷的异常种类,在方法定义的头部加上:

throws异常类名列表

例如,Thread类的方法sleep的定义为

publicstaticnativevoidsleep(longmills)throwsInterruptedException若采用throws声明方法抛掷的异常,Java语言编译器将检查调用该方法时是否进行异常捕捉。例如,程序5.3在run方法中调用线程类Thread类的sleep方法,如果将异常捕捉的语句去掉,编译时将提示:

Exception"InterruptedException"notcaughtordeclaredby"voidAd.run()"

该提示信息要求run方法捕捉处理该异常,或在定义run方法时声明该方法可能抛掷InterruptedException类型的异常,然后由调用该方法的代码捕捉处理该异常。6.2.3实例

程序6.3演示了try-catch和throw语句的使用,该程序在KeyboardInput类中定义了两个静态方法ReadInt和ReadDouble,从标准输入设备读取int、double类型数据。首先调用ReadLine方法读取一行字符串,然后将该字符串转换为int、double类型数据。如果在转换的过程中发生错误,输入了错误的数据,则抛掷NumberFormatException类的异常,ReadInt和ReadDouble方法捕捉该异常,然后抛掷Exception异常。ExceptionDemo类在main方法中捕捉异常,调用Exception类的方法getMessage获取错误信息。【程序6.3】异常处理实例。

importjava.io.IOException;

classKeyboardInput{

staticintReadInt()throwsException

{

Stringstr=ReadLine();

try{

returnnewInteger(str).intValue(); //将读入的字符串转换为int

}catch(NumberFormatExceptione){ thrownewException("输入数据错误");

}

}

staticdoubleReadDouble()throwsException{

Stringstr=ReadLine();

try{

returnnewDouble(str).doubleValue(); //将读入的字符串转换为double

}catch(NumberFormatExceptione){

thrownewException("输入数据错误");

} }

staticStringReadLine()

{

charin;

Stringinputstr="";

try{

in=(char)System.in.read();

while(in!='\n'){

if(in!='\r')

inputstr=inputstr+in;

in=(char)System.in.read(); }

}

catch(IOExceptione){

inputstr="";

}

returninputstr;

}

}

publicclassExceptionDemo

{ publicstaticvoidmain(String[]args)

{

try{

System.out.println("Theinputdoubleis"+KeyboardInput.ReadDouble());

System.out.println("Theinputintegeris"+KeyboardInput.ReadInt());

}catch(Exceptione){

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

}

}

}

6.3异 常 的 类 型

6.3.1Java异常类层次

Java中的所有的异常类都是从Throwable类派生出来的。Throwable类有两个直接子类:Error和Exception。

Error类及其子类主要用来描述一些Java运行时系统内部的错误或资源枯竭导致的错误,普通的程序不能从这类错误中恢复。应用程序不能抛掷这种类型的错误,这类错误出现的几率是很小的。

另一个异常类的分支是Exception类和它的子类。在编程中,对错误的处理主要是对这类错误的处理。类Exception是普通程序可以从中恢复的所有标准异常的超类。

Exception类又有两个分支:从RuntimeException中派生出来的类和不是从RuntimeException类中派生的类。这是根据错误发生的原因进行分类的。

RuntimeException是程序员编写程序不正确所导致的异常,RuntimeException类的错误又包括:错误的强制类型转换(ClassCastException)、数组越界访问(IndexOutOfBoundsException)、空指针操作(NullPointerException)等。这类错误Java语言不强制要求程序捕获。而其他的异常则是由于一些异常的情况造成的,不是程序本身的错误,比如:输入/输出错误(IOException)、试图为一个不存在的类找到一个代表它的class类的对象(ClassNotFoundException)等。这类异常Java语言要求程序必须处理,如果发生异常的方法本身不处理该异常,则方法头部必须使用throws。6.3.2创建自己的异常类

用户定义异常类是通过派生Exception类来创建的,这种异常类可以包含一个“普通”类所包含的任何东西。下面就是一个用户定义异常类的例子,它包含一个构造函数、几个变量以及方法。例如:

classMyExceptionextendsException{

privateintErrorCode;

MyException(intecode){

super(“自定义的异常类型”);

ErrorCode=ecode;

}

publicintgetErrorCode(){

returnErrorCode;

}

}

定义上面的异常类后可以通过下面的语句抛掷MyException类的异常:

thrownewMyException(1);

程序6.4演示了异常类的定义、异常抛掷和捕捉。程序运行后从键盘输入10个英文字母,如果输入非英文字母的字符,则抛掷自定义的notLetterException类型的异常。【程序6.4】异常类的定义、异常抛掷和捕捉。

importjava.io.IOException;

classnotLetterExceptionextendsException{ //异常类定义

publicnot

温馨提示

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

评论

0/150

提交评论