




已阅读5页,还剩50页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第5章Java例外处理,5.1异常的基本概念5.2异常的处理机制5.3异常类的类层次,5.1异常的基本概念,异常(Exception)是程序执行过程中出现的非正常事件,即各种意外情况。比如说:用户输入出错所需文件找不到运行时磁盘空间不够内存不够,算术运算错(数的溢出,被零除)数组下标越界当Java程序出现以上的错误时,就会在所处的方法中产生一个异常对象。这个异常对象包括错误的类型,错误出现时程序的运行状态以及对该错误的详细描述。下面我们先看一个简单的例子。,例5.1publicclassExceptionDemopublicstaticvoidmain(Stringargs)intx=100;System.out.println(Theresultis+x/10);System.out.println(Dividedbyzero:+x/0);,当我们对其编译后运行时,其对应的结果如下:c:jbuilder3javabinjavaExceptionDemoTheresultis10Exceptioninthreadmainjava.lang.ArithmeticException:/byzeroatExceptionDemo.main(ExceptionDemo.java:5)其意思是说,本程序执行到语句“System.out.println(Dividedbyzero:+x/0)”时,系统会抛出一个例外,该例外在Java中定义为ArithmeticException(即属于算术运算例外)。,5.2异常的处理机制,我们知道,一旦程序在执行的过程中出现异常,往往有两种处理方式:(1)当程序出现错误的时候,系统将终止程序的运行,如例5.1。在Java中这是属于运行异常,用户不加干预,完全交由系统对其进行处理。,(2)当程序出现错误时,采用捕捉抛出(catch-throw)的面向对象编程方式。该种方式是当程序运行出错时,系统和程序抛出各种标准类型的错误,程序捕捉该错误并进行相应处理。由于异常均以标准的形式提供,使得程序员能以统一的方式对异常进行处理。通常,Java的出错与异常处理采用“try,catch,throws”语句来实现,下面我们分别加以介绍。,5.2.1异常的直接捕获与处理:try-catchtry-catch语句构成Java对异常直接处理的基本处理单元,其一般语法如下:tryprogramwhereerrorsmayarisecatch(ExceptionClass1c)whattodowithitcatch(ExceptionClass2d)whattodowithit,上述用法中,可能出现异常的语句放在由try语句所括住的程序块中。try块管理其所包含的语句并定义与之相关的异常指针范围,它的后面必须至少接一个catch语句。catch语句块负责处理各对应类型的异常。实际编程过程中,如果我们对程序代码可能出现的异常不进行捕获,Java的编译环境就拒绝执行,并要求用户对其作出处理。看下例:,例5.2importjava.io.*;publicclassExceptionDemo1publicstaticvoidmain(Stringargs)inti;FileInputStreamfis=newFileInputStream(file_in.txt);,FileOutputStreamfos=newFileOutputStream(file_out.txt);while(i=fis.read()!=-1)fos.write(i);fis.close();fos.close();例5.2只是一个简单的文件输入/输出程序。该程序中定义了一个文件输入流和文件输出流,然后通过它们进行文件的拷贝。,当上述程序进行编译的时候,结果如下:c:JBUILD1javabinjavacExceptionDemo1.javaExceptionDemo1.java:5:Exceptionjava.io.FileNotFoundExceptionmustbecaught,oritmustbedeclaredinthethrowsclauseofthismethod.FileInputStreamfis=newFileInputStream(file_in.txt);ExceptionDemo1.java:7:Exceptionjava.io.IOExceptionmustbecaught,oritmustbedeclaredinthethrowsclauseofthismethod.while(i=fis.read()!=-1)2errors,系统异常信息告诉我们,两种异常程序员必须捕获,即FileNotFoundExcetion和IOException。对例外进行处理时,用户往往想知道异常的具体信息,我们可利用异常父类Throwable中提供的方法getMessage()得到有关异常事件的信息。方法printStackTrace()可用来跟踪异常事件发生时执行堆栈的内容。这样,例5.2可改写为,例5.3importjava.io.*;publicclassExceptionDemo1publicstaticvoidmain(Stringargs)inti;tryFileInputStreamfis=newFileInputStream(file_in.txt);FileOutputStreamfos=newFileOutputStream(file_out.txt);while(i=fis.read()!=-1)fos.write(i);,fis.close();fos.close();catch(FileNotFoundExceptione)System.out.println(Theerroris:+e.getMessage();e.printStackTrace(System.out);catch(IOExceptione)System.out.println(Theerroris:+e);,程序中增加了对例外的处理语句后,就顺利通过了编译。catch语句的执行顺序是先捕获最特殊的异常,之后逐渐一般化,因为,IOException是FileNotFoundException的父类。Java允许用户捕获实际需要捕获的异常类的超类,所以,一个catch语句就可以同时捕获多种异常。这样,例5.3中的try-catch语句又可以改写为try.catch(Exceptione)System.out.pritnln(Theerroris:+e.getMessage();,因为Exception类是FileNotFoundException类和IOException类的超类,所以对一段可能抛出大量不同类型的异常的程序来说,逐个捕获处理异常可能会较繁琐,而仅仅捕获它们父类的异常则会较方便。实际使用中,需要避免捕获最一般的异常类型(即超类Exception),因为捕获最一般的异常使得用户往往不能确切地判断异常的具体类型并作出相应的处理。针对例5.3,如果try-catch语句写为,try.catch(Exceptione)System.out.pritnln(Theerroris:+e.getMessage();catch(IOExceptione)System.out.println(Theerroris:+e);catch(FileNotFoundExceptione)System.out.println(Theerroris:+e.getMessage();e.printStackTrace(System.out);,则该异常的后两个catch捕获语句会始终匹配不到,造成编译器的混乱。所以说,捕获异常的顺序是和catch语句顺序相关的,希望读者注意它的用法。与异常处理语句try-catch相关的另一条语句是finally语句。它为例外处理提供一个统一的出口,使得在控制流转到程序的其他部分以前,能够对程序的状态作统一的管理,比如关闭文件或释放其他系统资源。实际使用中finally紧接于try-catch语句的最后一个catch块,基本语法如下:,tryprogramwhereerrorsmayarisecatch(ExceptionClass1c)whattodowithitcatch(ExceptionClass2d)whattodowithitfinally.,finally语句的执行是非常决断的、无条件的执行的。无论是否出现异常,也不管出现哪一种异常或即使try语句块中包含有return、break、continue等语句,均须执行finally语句块所包含的语句。这就是说,finally语句的作用与C+中类的析构函数相似。比如在例5.3中,我们打开了文件file_in、file_out进行读/写操作,如果产生了异常,就可能需中断,此时,对应的文件有可能无法正常关闭,这会对文件造成破坏。但使用finally语句后,就可把方法中的所有善后工作作统一处理,既增强程序的可读性,又避免了对系统或文件的损害。所以,例5.3可改写为,例5.4importjava.io.*;publicclassExceptionDemo1publicstaticvoidmain(Stringargs)inti;tryFileInputStreamfis=newFileInputStream(file_in.txt);FileOutputStreamfos=newFileOutputStream(file_out.txt);while(i=fis.read()!=-1)fos.write(i);,fis.close();fos.close();catch(FileNotFoundExceptione)System.out.println(Theerroris:+e.getMessage();e.printStackTrace(System.out);catch(IOExceptione),System.out.println(Theerroris:+e);finallyif(fis!=null|fos!=null);System.out.println(Nowclosingfile);fis.close();fos.close();,5.2.2异常的间接声明抛弃当在程序或代码块中出现异常时,Java语法要求要么对其捕获,要么在方法定义中用关键字throws声明异常类型并间接将其抛出,交给其调用者来进行处理。也就是说,异常对象可以从调用栈向后传播,直到有合适的方法对其进行捕获为止。例如:publictypemethodName(argsIfAny)throwsExceptionClass1,ExceptionClass2codeformethod,throws语句中同时可以给出多个异常类,说明该方法将不对这些异常进行处理,而是直接反馈给调用者。实际应用中,抛出的类可以是几个异常的父类。比如在上面代码中,假设ExceptionClass1、ExceptionClass2类的父类为super_Exception,那么我们可以简单地抛出类super_Exception。例如:publicvoidMaster()tryslaver();,catch(NumberFormatExceptione)/processherecatch(ArithmeticExceptione)/processherepublicvoidslaver()throwsNumberFormatException,ArithmeticException/codehere,5.2.3直接抛出异常throw语句表示直接抛出一个异常,后接一个可抛出的异常类对象。指令格式如下:throwExceptionObject;前面我们讨论的异常均由Java虚拟机或异常类的实例生成,而使用throw语句可以抛出程序员自行定义的异常类。例如:classExceptionDemo2extendsException.publicclassProcessException,publicvoidThrowmethod()if(/noexceptionoccurred)elsethrownewExceptionDemo2();当throw语句执行时,它后面的语句将不执行,此时程序转而寻找与之匹配的catch语句,执行相应的异常处理程序。,5.3异常类的类层次,Java语言采用继承的方式组织各种异常,所有的异常类都直接或间接地继承于类Throwable。我们可用图5.1描述异常的常用类层次。从图5.1中可以看出,Throwable类是所有异常类的父类。它分为两个子类:Error类和Exception类。Error类包括动态链接失败、虚拟机出错等异常,该类异常Java不要求捕获,同时系统也不会抛出该类异常。,图5.1异常的常用类层次,类Exception又可细分为运行异常(RuntimeException)和其他一般异常。与Error类相似,运行异常(RuntimeException)也不需要程序对其进行捕获并处理,因为它表示Java虚拟机在运行时所产生的异常。该类异常的产生非常普遍,如果在每个可能产生这种异常的地方都加以处理,程序就会变得无法理解,从而影响程序的可读性和高效性。继承于类Exception的异常代表非运行时异常,该类异常必须明确地加以捕获并处理,否则就无法通过编译。例如,在例5.3中对FileNotFoundException和IOException两类异常我们都作出了捕获并处理。,对于运行异常和错误来说,它们之间的区别主要在于对系统所造成的危害轻重不同,恢复正常的难易程度也不一样。错误可以说是一种致命的异常。比如说当遇到诸如LinkageError、VritualMachineError之类的错误时,系统是没有办法恢复的。而遇到除数为零的运行时异常ArithmeticException,我们可以给出捕获语句加以处理,不至于导致系统的崩溃。,最后,读者需要注意的是对异常的处理往往非常灵活。比如说对运行时异常一般不需要处理,但是假如需要输入一个整型数,而此时用户却输入一个字符串转换成整型,且不小心输入了非数字的字符串时,就会产生运行时异常类NumberFormatException。此时,若按照前面所说不对其加以捕获处理,系统就会被中断,无法进行下去,因此,程序中就需加入以下的代码:,Stringstr=DialogBox.request(PleaseinputadigitString:);Tryintd=Integer.parseInt(str);catch(NumberFormatExceptione)System.out.println(IllegaldigitStringin+str);下面给出一些常见的错误(Error)(表5.1)、一般异常(表5.2)及运行异常(RuntimeException)(表5.3)的基本格式及功能。,表5.1Java常见错误列表,表5.2Java常见的一般异常列表,表5.3Java常见的运行异常列表,当我们在使用异常时,应尽可能使用Java类库中已经定义好的类。前面我们讨论过的throw语句可以抛出用户自定义的异常类,其实,Java类库中提供了大多数常用的类库,往往只是在很少的情况下才需要用户自己定义异常类。用户自定义的异常类必须是Throwable的直接或间接的子类。总之,当我们使用异常的时候,可以参考以下几点建议:,(1)对运行时异常类的处理,由于其发生的多样性,程序中可不对它进行处理,而直接交给系统去处理。(2)如果我们确定异常在程序中产生的地点或时间,则需像对一般异常处理的方式一样对其捕获并处理。(3)当Java所给定的异常类不能满足我们要求时,需要自定义异常类。如果该异常符合条件1,则应定义为运行时异常;如果符合条件2,则应定义为一般异常类。,下面我们给出一个完整的例子。该例是模拟整型除法运算,但使用了Java的图形用户界面,读者可以不管程序的其他用法,着重关注程序中对异常的处理方法。类DivisionFrame中的方法performDivision进行除法的运算,其中可能产生两种异常:NumberFormatException和ArithmeticException,但在该方法中并没有对它们进行捕获,只是通过throws语句将它们简单抛出,最后由调用者来进行捕获并处理。,例5.5publicclassMainpublicstaticvoidmain(Stringargs)DivisionFramedivWin=newDivisionFrame();divWin.setVisible(true);importjavax.swing.*;importjava.awt.*;importjava.awt.event.*;,publicclassDivisionFrameextendsExitFrame/instancevariablesprivateJTextFieldnumerator,denominator,result;privateStringtask=Enterintegersandpress=toperformdivision.;privateJLabeltaskMsg=newJLabel(task,JLabel.CENTER);privateStringwelcome=Welcometothedeluxeinteger-divisioncalculator;privateJLabelstatusMsg=newJLabel(welcome,JLabel.CENTER);,/constructorpublicDivisionFrame()setTitle(PerformingIntegerDivision);setBounds(50,100,750,200);Fontf=newFont(SansSerif,Font.BOLD,30);taskMsg.setFont(f);taskMsg.setForeground(Color.blue);statusMsg.setFont(f);statusMsg.setForeground(Color.blue);numerator=newJTextField(0,7);,numerator.setFont(f);denominator=newJTextField(1,7);denominator.setFont(f);result=newJTextField(0,7);result.setFont(f);JLabeldivSign=newJLabel(/,JLabel.CENTER);divSign.setFont(newFont(SansSerif,Font.BOLD,50);divSign.setForeground(Color.black);JButtonequalBut=newJButton(=);equalBut.setFont(f);equalBut.addActionListener(newActionListener(),publicvoidactionPerformed(ActionEventevt)tryperformDivision();catch(NumberFormatExceptione)statusMsg.setForeground(Color.r
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 大学课件辅导
- 张家口市人民医院胃镜检查医师上岗资格认证
- 承德市人民医院老年心力衰竭急性加重处理考核
- 2025广东运管所郁南县亮丽路灯管理有限公司招聘员工1名考前自测高频考点模拟试题及参考答案详解
- 北京市中医院喉癌部分切除术操作资格认证
- 2025第二人民医院感染指标判读考核
- 沧州市人民医院伤口分期标准掌握考核
- 2025中心医院医疗器械消毒灭菌考核
- 天津市人民医院绒毛穿刺取样技术专项技能考核
- 2025人民医院烧伤康复治疗方案制定考核
- 迪尔凯姆社会学主义的巨擎汇总课件
- 家庭经济困难学生认定申请表
- 血栓性血小板减少性紫癜ttp汇编课件
- 阀门安装及阀门安装施工方案
- 大学数学《实变函数》电子教案
- YY/T 0640-2008无源外科植入物通用要求
- GB/T 29531-2013泵的振动测量与评价方法
- GB/T 2637-2016安瓿
- 循环系统查体培训课件
- 数轴上的动点问题课件
- 省级公开课(一等奖)雨巷-戴望舒课件
评论
0/150
提交评论