版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
异常1内容5.1异常的抛出与捕获 5.2处理异常 5.3自定义异常 2异常正常(normal)的程序沿着控制流执行。在执行过程中可能会发生某事件导致程序无法继续沿着控制流执行,这种不期望发生的事件称为异常(exception)。异常是“异常事件(exceptionalevent)”的简称。3上课正常流程4打开投影等设备;DO
教师在讲台上讲解;
板书;
没有粉笔
提问;WHILE下课时间未到宣布下课;关闭投影等设备异常发生打开投影等设备;DO
教师在讲台上讲解;
板书;
没有粉笔
提问;WHILE下课时间未到宣布下课;关闭投影等设备5其它教室寻找粉笔抛出程序把异常事件创建为“异常对象”并传递给Java虚拟机,这个过程称为“抛出(throw)”。异常对象中包含了错误信息以及程序在异常出现时的状态。异常是“少而不同”的事件,并不总会发生。6捕获如果程序需要对可能发生异常事件按预案进行处理,那么程序就设计一段代码首先从虚拟机中取出异常对象,这个过程称为“捕获(catch)”,然后再进行处理7例子在第3行首先创建了一个只具有三个元素的数组对象,即数组的长度为3,按照Java语言对数组的访问规则,应分别通过a[0]、a[1]和a[2]访问这三个数组对象。然而第4行的语句却试图访问a[3]。当程序执行到第4行的语句时,println方法就会向虚拟机抛出ArrayIndexOutOfBoundsException类型的异常对象由于程序没有设计任何预案来应对该异常,程序终止执行8ArrayIndexOutOfBoundsExceptionDemo.java例第4行试图访问静态变量a;而a没有引用任何数组对象,其初值为null。所以当程序运行到第4行会抛出空指针异常,并在控制台输出如下消息后终止执行9NullPointerExceptionDemo.java异常类运行时刻异常RuntimeException也称为免检(unchecked)异常所谓“免检”,指这类异常导致程序无法继续执行下去,只能终止,不必为这类异常设计处理程序;而Exceptin类的其它子类都是受检(checked)异常所谓“受检”,指程序必须安排预案,一旦异常出现如何处置。10例子从文件data.txt中读取体重。1134
56.7
58
25FileNotFoundExceptionDemo.javaIOException是典型的受检异常。FileNotFoundException是一种IOExceptinon。受检异常编译器强制在程序中必须对可能出现的IOException进行处理。处理的方法有两种:捕获声明抛出声明抛出是较为简单的处理方法:如果在方法体中可能抛出某类型的异常,那么只许把该异常类型在方法头部使用保留字throws声明抛出即可。该方法的调用者看到这个声明,再进行处理。12处理方法:声明抛出13
1importjava.util.Scanner;2importjava.io.File;3importjava.io.FileNotFoundException;4publicclassFileNotFoundExceptionDemo{5publicstaticvoidmain(String[]args)throwsFileNotFoundException{6Scannersc=newScanner(newFile("input.txt"));7System.out.println(sc.nextLine());8sc.close();9}10}
抛给方法的调用者,由方法的调用者处理处理方法:捕获异常141importjava.util.Scanner;
2importjava.io.File;
3importjava.io.FileNotFoundException;
4public
classCatchDemo{
5
public
static
voidmain(String[]args){
6Scannersc=null;
7
try
{
8sc=newScanner(newFile("input.txt"));
9System.out.println(sc.nextLine());
10sc.close();
11}catch(FileNotFoundExceptione){
12e.printStackTrace();
13System.out.println(e.getMessage());
14}
15}
16}把可能抛出异常的程序片段使用保留字try后的一对大括号“{}”中。这对大括号括起来的语句序列称为try块(tryblock)。把对异常处理的程序片段放在保留字catch后面的大括号中,这对大括号“{}”括起来的语句序列称为catch块引用异常对象为了在catch块中引用try块中抛出的异常对象,在保留字catch其后的catch块之间使用小括号“()”括起来了异常对象引用变量声明。第12行调用了实例方法printStackTrace输出异常对象的栈跟踪信息,这是给程序员看,用来调试程序用的;第13行调用了实例方法getMessage输出异常提示消息,这是给最终用户看的。执行catch块完毕,继续执行try-catch语句的后随语句。15抛出和捕获在某次运行中,try块中的某条语句可能会抛出异常对象,此例中是FileNotFoundException类型的异常对象;这个异常对象交给了JVM;程序的控制发生转移,转到catch块执行;catch块通过声明的FileNotFoundException类型的引用变量e访问try块中抛出的异常对象,一旦e能够引用这个异常对象,则称捕捉到了该异常。16除了RuntimeException以外,其它Exception类的后代类都是受检异常。对于所有受检异常,程序必须显示地声明如何进行处理。17try-with-resource语句try块中第8行的语句抛出异常,那么就不会执行第10行的关闭语句close(),从无法释放资源。解决方法清理现场和释放资源的语句都放到finally块中try-with-resource18FinallyDemo.java一般形式try{……}catch(Exception<引用变量名>){……}finally{……}19无论异常发生与否,finally块总会执行try块至少与之关联一个catch块try-with-resource声明及创建Scanner对象的语句移到保留字try与大括号间的小括号中这样无需使用finally块可以通过分号分隔,声明多个资源论异常是否抛出,占用的资源都会被自动释放20WithResourceDemo.javaWithMultiResourceDemo一个try块关联多个catch块如果try块中抛出异常,Java的异常处理系统就自上而下依次将该异常的类型与catch中声明的类型进行匹配(match)一旦匹配,就执行相应的catch块,catch块执行完毕,则整个try-catch语句执行完毕,继续执行该语句的后随语句匹配的意思是:抛出的异常对象的引用能够合法地赋值异常处理器声明的参数21MultiCatchDemo.java异常的匹配如果当前文件夹中没有input.txt则抛出FileNotFoundException异常;如果有input.txt但里面是空的,一行也没有,则抛出NoSuchElementException异常;如果试图读取input.txt时使用的对象已经关闭,则抛出IllegalStateException异常。22注意下面的try-catch语句中所有期望的异常都能赋值给第一个catch块中的e,导致其它catch块不会被执行23try{...}catch(Exceptione){System.out.println(e.getMessage());}catch(IOExceptione){System.out.println(e.getMessage());}catch(FileNotFoundExceptione){System.out.println(e.getMessage());}异常的匹配一个try块与三个catch块相关联。自上而下,catch块声明的异常类型分别是FileNotFoundExceptionNoSuchElementExceptionIllegalStateException如果在try块中抛出了FileNotFoundException类型的异常对象,由于该类型与FileNotFoundException匹配,那么执行的是第一个catch块;如果在try块中抛出了NoSuchElementException类型的异常对象,由于该类型与NoSuchElementException匹配,那么执行的是第二个catch块;如果在try块中抛出了IllegalStateException类型的异常对象,由于该类型与IllegalStateException匹配,那么执行的是第三个catch块。24异常的匹配把期望捕获的异常通过|声明在一起25MultiCatchInOneDemo.java抛出和捕获Java程序把异常事件作为对象传递给JVM,这个对象就称为“异常对象”。这个过程称为“抛出异常(throwinganexception)”。异常对象中包含了错误信息以及程序在异常出现时的状态。负责对异常进行处理的程序需要从JVM中取出异常对象,这个过程称为“捕获”。26抛出和捕获使用try-catch语句把可能产生异常的语句安排在try块中把对异常进行处理的语句安排在catch块中27总结:try-catch保留字try以及其后由一对大括号“{}”括起来的语句序列称为try块(tryblock)。try块中的语句有可能抛出异常。保留字catch、紧跟其后的有小括号“()”括起来的异常对象引用变量声明、以及其后由一对大括号“{}”括起来的语句序列称为catch块。一旦try块中的某条语句抛出异常对象,就不再继续执行该语句以及其后随语句,而是转移到catch块执行。28总结:try-catch执行catch块时,通过声明的异常对象引用变量(例如e)可以访问异常对象的具体内容。执行catch块完毕,继续执行try-catch语句的后随语句。29异常处理器catch块中处理异常的代码称为异常处理器(exceptionhandler)。30异常的传播methodA是methodB的调用者,将来methodA在执行含有methodB调用的语句时可能会产生异常。此时methodA同样有两种异常处理方式可供选择:捕获抛出31异常的传播如果methodA使用throws声明把异常交给调用者处理,那么在其调用者main方法中又遇到同样问题。当然main方法同样有两种异常处理方式可供选择:捕获抛出32异常的传播main方法是整个程序的入口,如果一个异常对象由main方法声明抛出,交由调用者处理,那么JVM就会输出一些异常对象的信息,然后中止程序执行。33总结Java异常处理系统的任务就是当程序中的异常发生后,为其寻找异常处理器。这个寻找是沿着方法的调用反向进行,直到main方法。34方法调用链35注意如果抛出异常的语句在try块中,但是该异常不能与try-catch语句中的任何catch块声明的异常类型相匹配,那么该异常就沿着方法调用链向调用者方向传播。36捕获异常main调用了方法methodA,而methodA调用了methodB。假设在方法methodB抛出异常。如果该异常类型匹配ExceptionB,那么这个异常就被捕捉到并进行处理。如果该异常类型不匹配ExceptionB,那么停止执行methodB,控制返回到调用者methodA对方法methodB的调用语句处。如果异常类型与methodB所在try-catch语句中的异常处理器声明的异常类型ExceptionA匹配,那么就执行该异常处理器。37捕获异常如果该异常类型也不匹配ExceptionA,那么停止执行methodA,控制返回到调用者main对方法methodA的调用语句处。如果异常类型与methodA所在try-catch语句中的异常处理器声明的异常类型ExceptionM匹配,那么就执行该异常处理器。如果该异常类型仍然与ExceptionM不匹配,程序终止。38注意(一)一个try块至少有一个catch块关联,可与多个catch块关联;(二)finally块可有可无;(三)必须声明如何处理受检异常;(四)异常对象由程序中某个方法在执行期间抛出给JVM,而catch块则声明要求JVM交递的异常;(五)如果JVM存在某个异常对象,但没有找到等待该异常的任何catch块,则JVM终止程序运行;(六)不能在finally块中使用return。在finally块中的return返回后方法结束执行,不会再执行try块中的return语句。39注意如果catch块中有return语句,仍然先执行finally块,再return;如果catch块中有System.exit()语句,则不会执行finally块。405.3自定义异常41例java.lang.Math类的类方法addExact,该方法把给定的两个int类型参数求和,如果加法运算的结果溢出,超出了int类型整数的范围,那么抛出ArithmeticException异常。42publicstaticintaddExact(intx,inty){intr=x+y;//Overflowiff//bothargumentshavetheoppositesignoftheresultif(((x^r)&(y^r))<0){thrownewArithmeticException("integeroverflow");}returnr;}MathDemo.java第4行把2和3相加,结果没有溢出;第5行把在java.lang.Integer中定义的整数最大值MAX_VALUE即0x7fffffff与2相加,发生溢出例形式参数年龄为负数则抛出异常43NegativeAgeExceptionDemo.java定义异常自定义异常需要做三件事情:定义异常;声明异常抛出;捕获异常。其中,前两件事情做好之后,第三件事情就与前文讲述的异常的捕获和处理一样了。一般通过继承java.lang.Exception定义异常类44例setAge()方法在参数大于等于0时,执行正常流程;否则,应当抛出异常。45AgeExceptionDemo.java定义异常首先定义一个新的异常类型。46OutOfAgeRangeException.java声明抛出定义好异常类型后,修改setAge方法,使其抛出异常对象。这个修改有两个地方:在合适的位置添加throw语句;在方法的头部使用throws声明抛出。47捕获异常经过以上两个步骤:定义了异常类型在方法中声明和抛出了异常,接下来就和使用JDK中异常一样,捕获自定义异常OutOfRangeException了48自定义异常通常需要设计一个以给最终用户看的异常提示消息为参数的构造方法,该方法通常通过调用父类的带有字符串参数的构造函数来完成在适当位置抛出在方法的头部使用throwsMyCustomException声明本方法可能会抛出异常。如果自定义异常是RuntimeException则无需在方法头部声明抛出。调用可能抛出自定义异常的方法的地方用try-catch块捕获并处理该异常49MyCustomExceptionUtils.javaUtilsDemo.java异常处理过程catch块执行完毕后去执行finally块和try-catch语句的后续语句50ProcessDemo.javaJava异常处理机制的优势Java异常处理机制提供了把异常处理代码从正常处理代码中分离出来的能力。在传统程序设计里,负责异常处理的代码和正常的代码流程交织混杂,降低了可读性和可维护性。51包装为自定义异常在catch块中不能仅仅输出一些信息,还得要有流程控制语句以避免继续执行trycatch语句的后续语句。一个很常见的做法是捕获标准异常并包装为自定义异常包装异常时,一定要把原始的异常设置为cause(Exception有构造方法可以传入cause)52WrapDemo.java例:弹栈pop可返回null53publicclassArrayStackimplementsStack{
privateObject[]objectArray; privateinttopOfStack; privatestaticfinalintCAPACITY=128; publicObjectpop(){ if(this.isEmpty()) returnnull; else{ returnobjectArray[topOfStack--]; } } publicbooleanisEmpty(){ returntopOfStack==-1; } …}例:弹栈pop可返回null(续)54publicstaticvoidmain(String[]args){Stacks=newArrayStack();Objectitem=s.pop();if(item==null){//调用者负责判断返回值
System.out.println("Thestackisempty.");else{System.out.println("Theelementonthetophasbeenreleased.");}}例问题是:完成正常处理流程的语句:System.out.println("Theelementonthetophasbeenreleased.");
嵌入在了状态检查语句中,而且一般都安排在最后,即排除了各种异常情形后才执行。这样,在读程序的时候,迫使读者先去阅读和理解异常处理的情形,而不是先去阅读和理解正常流程的处理。毕竟,异常情形发生的可能性很低。55例客户代码还得必须使用一个特殊的方法返回值获取这个方法执行正常与否的状态。上面的ArrayStack的客代码使用一个特殊的返回值null判断pop方法执行状态以便进行相应处理。有的时候很难约定一个特殊的返回值。56使用异常57publicObjectpop()throwsException{if(this.isEmpty()){thrownewException(this+"isempty");}else{returnobjectArray[topOfStack--];}}publicstaticvoidmain(String[]args){Stacks=newArrayStack();Objectitem;try{item=s.pop();}catch(Exceptione){System.out.println(e.getMessage());}}异常处理版本的文件读写try-catch-finallytrywithresource58FlowSeperation.javaFlowSeperationTWR.java断言断言的语法形式为:assert<逻辑表达式>断言语句由一个保留字assert和一个逻辑表达式组成。其中,逻辑表达式在断言语句的位置应该为计值真。如果为假,则抛出AssertionError类型的异常。59求平方根方法使用断言的版本60publicclassSquareRoot{
publicstaticvoidmain(String[]args){ doublec=-4; System.out.println(squareRoot(c)); }
staticdoublesquareRoot(doublec){ finaldoubleepsilon=1e-15; assertc>=0;//"负数不能求平方根; doubleestimate=c; while(Math.abs(estimate-c/estimate)>epsilon*estimate){ estimate=(estimate+c/estimate)/2.0; } returnestimate; }}求平方根方法使用断言的版本这个版本的求平方根方法squareRoot在真正开始计算参数c的平方根之前断言c>=0。如果表达式c>=0计值为真,程序继续执行;若果表达式c>=0计值为假,则抛出java.lang.AssertionError类型的异常对象。61Exceptioninthread"main"java.lang.AssertionError atSquareRoot.squareRoot(SquareRoot.java:12) atSquareRoot.main(SquareRoot.java:7)设置对断言的支持62632019计科赵轶楠命令行参数如果使用命令进行编译,则可以指定java的命令行参数ea。对于本例而言,运行时应使用命令:
>java-ea-cp.SquareRoot如果在类中包含断言而在运行时没有指定-ea参数,那么所有的断言语句将被忽略。64说明出错原因语句还可以写成: assertc>=0:"负数不能求平方根";即在关系表达式后面增加一个冒号,然后是一个说明出错原因的字符串。这样,当表达式计值为假,抛出的异常就能把这些字符串显示出来:65说明出错原因66Exceptioninthread"main"java.lang.AssertionError:负数不能求平方根 atSquareRoot.squareRoot(SquareRoot.java
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 保险协议书签订前叫什么期
- 租房协议书壁纸
- 2025年出租车司机因病需要与公司终止劳动合同
- 2025餐厅整体转让合同范本
- 2025年成人英语培训行业不同级别课程学习效果与就业竞争力分析报告
- 2025工业用地转让合同
- 江川小学结业试卷及答案
- 2025年便利店租赁合同
- 2025广东省劳动合同样本下载
- 2025煤炭储存场地租赁合同模板
- 2025年江苏安全员c考试题目及答案
- 多人合伙建房合同范本
- 2025年胸膜炎护理试题及答案
- 上海购房合同(标准版)
- 2025年青海省公务员申论考试真题试卷(含答案)
- 浙江省浙南名校联盟2025-2026学年高三上学期10月联考英语试题
- 2026届新高考英语冲刺热点复习 2025年新高考1卷阅读理解D篇说题
- 新能源公交安全培训内容课件
- 企业人力资源数字化管理平台方案
- 2025年广东铁投集团校园招聘笔试参考题库附带答案详解
- 工作快乐生活演讲稿
评论
0/150
提交评论