《Java教材》PPT课件.ppt_第1页
《Java教材》PPT课件.ppt_第2页
《Java教材》PPT课件.ppt_第3页
《Java教材》PPT课件.ppt_第4页
《Java教材》PPT课件.ppt_第5页
已阅读5页,还剩54页未读 继续免费阅读

下载本文档

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

文档简介

第6章 异常(Exception)处理,教学目的要求,1.理解异常概念,理解Java 中抛弃异常和声明抛弃异常的区别与联系; 2.掌握Java的异常处理机制,学会如何合理应用异常处理机制; 3.会使用捕获异常和声明抛弃异常的两种异常处理的方法。,6.1 异常的概念 6.2 异常处理 6.3 自定义异常处理类 6.4 应用举例,本章内容,1、异常的概念,在进行程序设计时,错误的产生是不可避免的,如何处理错误?把错误交给谁去处理?程序又该如何从错误中恢复?这是任何程序设计语言都要解决的问题。 所谓错误,是在程序运行过程中发生的异常事件,比如除0溢出、数组越界、文件找不到等,这些事件的发生将阻止程序的正常运行。为了加强程序的鲁棒性(强壮性,robust),程序设计时,必须考虑到可能发生的异常事件并做出相应的处理。,6.1 异常的概念,在C语言中,通过使用if语句来判断是否出现了错误,同时,调用函数通过被调用函数的返回值感知在被调用函数中产生的错误事件并进行处理。 但是,这种错误处理机制会导致不少问题,因为在很多情况下需要知道错误产生的内部细节。 通常,用全局变量Errno来存储一个异常事件的类型,这容易导致误用,因为一个Errno的值有可能在被处理前被另外的错误覆盖掉。此外,即使最优美的C语言程序,为了处理异常情况,也常常求助于goto语句。,没有错误处理的程序: openTheFile; determine its size; allocate that much memory; read-file closeTheFile; ,6.1 异常的概念,6.1 异常的概念,以常规方法处理错误: openFiles; if (theFilesOpen) determine the length of the file; if (gotTheFileLength) allocate that much memory; if (gotEnoughMemory) read the file into memory; if (readFailed) errorCode=-1; else errorCode = -2; else errorCode=-3; else errorCode=-4 ; else errorCode=-5;,以常规方法处理错误存在的问题: 观察前面的程序,大家会发现大部分精力花在出错处理上了 只把能够想到的错误考虑到,对以外的情况无法处理 程序可读性差,大量的错误处理代码混杂在程序中 出错返回信息量太少,无法更确切的了解错误状况或原因,6.1 异常的概念,6.1 异常的概念,Java通过面向对象的方法来处理程序错误,在Java中,错误被称为异常(Exception)。 在一个方法的运行过程中,如果发生了异常,则这个方法(或者是Java虚拟机)生成一个代表该异常的对象(包含了该异常的详细信息),并把它交给运行时系统,运行时系统寻找相应的代码来处理这一异常。我们把生成异常对象并把它提交给运行时系统的过程称为抛弃(throw)一个异常。 运行时系统在方法的调用栈中查找,从生成异常的方法开始进行回朔,直到找到包含相应异常处理的方法为止,这一个过程称为捕获(catch)一个异常。,6.1 异常的概念,用异常的形式处理错误: try openTheFile; determine its size; allocate that much memory; read-File; closeTheFile; catch(fileopenFailed) dosomething; catch(sizeDetermineFailed) dosomething; catch(memoryAllocateFailed) dosomething; catch(readFailed) dosomething; catch(fileCloseFailed) dosomething; finally dosomething; ,6.1 异常的概念,异常机制的优点: 把错误处理代码从常规代码中分离出来 按错误类型和差别分组(类Exception,派生) 对无法预测的错误的捕获和处理(基类) 克服了传统方法的错误信息有限的问题(getMessage) 把错误传播给调用堆栈(比较:全局变量,返回值),6.1 异常的概念,什么情况下使用异常机制? 当方法因为自身无法控制的原因而不能完成其任务 文件不存在,网络连接无法建立 处理在方法、类库、类中抛出的异常 如FileInputStream.read产生IOException 在大的项目中采用统一的方式处理错误时 如编写一个文字处理器 异常应该是不经常发生但却可能发生的故障 一定发生的事件不应该用异常机制来处理 异常处理用于使系统从故障中恢复 提示信息/不产生无效的结果/释放资源,不同的异常处理策略 关键性应用(处理所有异常) 实验软件(可以忽略许多异常) 处理异常时的注意事项 终止程序会导致资源泄漏,利用异常处理释放资源 尽可能近地处理异常,这样程序清晰易读 能在局部处理的错误不要使用异常机制 异常机制的处理比正常处理效率低,6.1 异常的概念,6.1 异常的概念,异常机制的关键步骤 try 定义可能产生异常的代码段 catch (Etype e) 用于捕获一个异常 finally 用于做统一的事后处理,如释放资源 throw e; 用于抛出一个异常 throws Etype1, Etype2 用于声明方法可能抛出的异常类型,throw / throws try-catch-finally,6.1 异常的概念,程序中的异常不外乎两种情况:一种是运行环境不能满足程序运行的要求而出错;一种是程序要解决的问题的约束而导致的。 不管是哪种情况,编写程序时,程序员要考虑到程序运行时可能遇到的各种情况(条件),并进行处理;如果不能处理,或者不知该如何处理,就可以认为是一种错误,这时,就需要交给别人去处理。 以前,是通过返回错误代码来提示别人程序有错误;在Java中,则是通过异常机制通知别人出错信息。,6.1 异常的概念,Java语言的异常处理方法有下列主要优点: Java通过面向对象的方法进行异常处理,把各种不同的异常事件进行分类,体现了良好的层次性,提供了良好的接口。 Java的异常处理机制使得处理异常的代码和“常规”代码分开,减少了代码的数量,同时增强了程序的可读性。 Java的异常处理机制使得异常事件可以沿调用栈自动向上传播,而不是C/C+语言中通过函数的返回值来传播,这样可以传递更多的信息并且简化代码的编写。 由于把异常事件当成对象来处理,利用类的层次性我们可以把多个具有相同父类的异常统一处理,也可以区分不同的异常分别处理,使用非常灵活。 Java异常处理机制为具有动态运行特性的复杂程序提供了强有力的控制方式。,6.2 异常处理,6.2.1 Java中的Throwable类 Java中的所有异常都是由Throwable类的子类生成的对象,所有的异常类都是Throwable类的子类或子类的子类。图6.1给出了部分Java中部分错误类、异常类的继承关系。,根据程序对错误与异常的处理方式,可以将Java中的异常分为三类: Error:由Java虚拟机生成并抛出,包括动态链接失败、虚拟机错误等,Java程序不做处理。 Runtime Exception:Java虚拟机在运行时生成的异常,如被0除等系统错误、数组下标超范围等,其产生比较频繁,处理麻烦,对程序可读性和运行效率影响太大。因此由系统检测, 用户可不做处理,系统将它们交给缺省的异常处理程序(当然,必要时,用户可对其处理)。 Exception:一般程序中可预知的问题,其产生的异常可能会带来意想不到的结果,因此Java编译器要求Java程序必须捕获或声明所有的非运行时异常。,6.2 异常处理,6.2 异常处理,6.2 异常处理 Throwable类的方法,Throwable() Throwable(String message) String toString() “classname” : “getMessage()” String getMessage() String getLocalizedMessage() void printStackTrace() void printStackTrace(PrintStream s) void printStackTrace(PrintWriter s) Throwable fillInStackTrace(),77: public static void main(String args) 78: try 79: testThrowable(); 80: 81: catch (Throwable t) 82: System.err.println(t.toString(); 83: System.err.println(t.getMessage(); 84: System.err.println(t.getLocalizedMessage(); 85: t.printStackTrace(); 86: 87: 136: static void testThrowable() throws Throwable 137: throw new Throwable(“测试 Throwable 的用法。“); 138: java.lang.Throwable: 测试 Throwable 的用法。 测试 Throwable 的用法。 测试 Throwable 的用法。 java.lang.Throwable: 测试 Throwable 的用法。 at test.Untitled1.testThrowable(Untitled1.java:137) at test.Untitled1.main(Untitled1.java:79),77: public static void main(String args) 78: try 79: testThrowable(); 80: 81: catch (Throwable t) 82: System.err.println(t.toString(); 83: System.err.println(t.getMessage(); 84: System.err.println(t.getLocalizedMessage(); 85: t.printStackTrace(System.err); 86: 87: 136: static void testThrowable() throws Throwable 137: throw new Throwable(); 138: java.lang.Throwable null null java.lang.Throwable at test.Untitled1.testThrowable(Untitled1.java:137) at test.Untitled1.main(Untitled1.java:79),6.2 异常处理 一些常用的异常类,Error (all in java.lang) LinkageError ThreadDeath VirtualMachineError InternalError OutOfMemoryError StackOverflowError UnknownError AWTError (in java.awt) ,Exception (in java.lang) ClassNotFoundException CloneNotSupportedException InterruptedException RuntimeException ArithmeticException ClassCastException InllegalArgumentException InllegalThreadStateException NumberFormatException,6.2 异常处理 一些常用的异常类,RuntimeException InllegalMonitorStateException InllegalStateException IndexOutOfBoundsException ArrayIndexOutObBoundsException StringIndexOutObBoundsException NegativeArraySizeException NullPointerException SecurityException EmptyStackException (in java.util) MissingResourceException (in java.util) NoSuchElementException (in java.util) ,6.2 异常处理 一些常用的异常类,Exception IOException (in java.io) CharConversionException EOFException FileNotFoundException InterruptedIOException StreamCorruptedException J.MalformedURLException ,6.2 异常处理 一些常用的异常类,异常示例: (1)编译时异常:在程序中必须对其进行处理,否则编译器会指出错误。 在使用能够产生异常的方法而没有捕获和处理,程序将不能通过编译。 (2)运行时异常:程序中可以不做处理,直接由运行时系统来处理。,6.2 异常处理,6.2.2 try-catch-finally语句 Java的异常处理是通过3个关键词来实现的:try-catch-finally。用try来监视执行一段程序,如果出现异常,系统就会抛出(throws)异常,可以通过异常的类型来捕捉(catch)并处理它,或最后(finally)由缺省处理方法来处理。,6.2 异常处理-捕获异常,try代码段包含可能产生异常的代码 try代码段后跟有一个或多个catch代码段 每个catch代码段声明其能处理的一种特定类型的异常 每个catch代码段都是一段异常处理代码 程序继续执行最后一个catch代码段后的代码 (或执行完finally代码段后) 不同的代码段是不同的作用域,不可访问相互之间定义的局部变量,try /接受监视的程序块,在此区域内发生 /的异常,由catch中指定的程序处理; / 不能有其它语句分隔 catch(要处理的异常种类和标识符) /处理异常; catch(要处理的异常种类和标识符) /处理异常; finally /最终处理(缺省处理); /Other Statements,6.2 异常处理-捕获异常,6.2 异常处理-捕获异常,try语句 捕获异常的第一步就是用try 语句指定了一段代码,该段代码就是一次捕获并处理异常的范围。在执行过程中,该段代码可能会产生并抛弃一个或多个异常,因此,它后面的catch语句进行捕获时也要做相应的处理。 如果没有异常产生,所有的catch代码段都被略过不执行。,6.2 异常处理-捕获异常,catch语句 每个try语句必须伴随一个或多个catch语句,用于捕获try代码块所产生的异常并做相应的处理。 catch语句有一个形式参数,用于指明其所能捕获得异常类型,运行时系统通过参数值把被抛弃的异常对象传递给catch语句。 程序设计中要根据具体的情况来选择catch语句的异常处理类型,一般应该按照try代码块中异常可能产生的顺序及其真正类型进行捕获和处理,尽量避免选择最一般的类型作为catch语句中指定要捕获的类型。 当然也可以用一个catch语句处理多个异常类型,这时它的异常类型应该是这多个异常类型的父类,但这种方式使得在程序中不能确切判断异常的具体类型。,public class ExceptionDemo public static void main(String args) try FileInputStream fis = new FileInputStream(“test1.txt“); int b; while( (b=fis.read()!=-1 ) System.out.print(b); fis.close(); catch(FileNotFoundException e) catch(IOException e) ,catch(IOException e) catch(FileNotFoundException e) /永远不会被执行 ,catch(Exception e) 捕获所有Exception catch(Throwable t) 捕获Exception和Error,catch语句 异常总是由距离产生异常最近的匹配catch代码段处理 如果没有相应的异常处理, 则异常被交给上一层try代码段进行处理 异常处理的查找依据类型匹配原则顺序进行 第一个匹配的异常处理被执行,当异常处理执行完毕,程序接着最后一个catch代码段后的语句执行 异常处理的顺序影响到异常的处理 子类异常可被父类异常处理捕获 不要先捕获父类异常,再捕获子类异常 如果找不到相应的异常处理 非GUI程序将结束程序执行; Applet或GUI程序则回复到事件处理状态,6.2 异常处理-捕获异常,6.2 异常处理-捕获异常,尽量避免用一般类型作为catch中指定要捕获的类型。 一般应该按照try代码块中异常可能产生的顺序及其真正类型进行捕获和处理, 在异常处理中无法访问try代码段中声明的变量 因为此时try代码段已经退出了,异常处理所需要的任何信息一般都应该通过异常对象来传递 在使用方法时尽量直接处理该方法可能产生的异常 这样你的程序就会更健壮 在使用库方法之前,应该先仔细阅读说明文档 那里会介绍方法可能产生的异常以及异常产生的条件 在使用各种异常类之前也应该先仔细阅读说明文档 那里会介绍异常的具体含义及异常产生的条件,在catch代码段中产生的异常不是由相同try的后续catch代码段处理,而是由包含整个try-catch结构的上层try代码段检测并处理 可以把catch到的异常对象再次抛出,使上层try-catch结构继续处理该异常事件;也可以把异常对象转换为其它异常对象 catch (Exception e) throw e; try-catch机制不该被用于流程控制,异常情形应该是很稀少的,而不是经常性的 catch中指定要捕获的类型必须是try块中有可能出现的异常,否则编译通不过,6.2 异常处理-捕获异常,public class TestTryCatchThrow public static void main(String args) try if (args.length 1) throw new Exception(“没有参数!”); InputStream in = new FileInputStream(args0); / readInt可能产生IOException,EOFException int i = in.read(); System.out.println(“读出的整数为:”+ i); catch (EOFException e) System.out.println(“错误:文件格式存在问题!”); catch (IOException e) System.out.println(“错误:文件操作中出现问题!”); catch (Exception e) System.out.println(“错误:” + e.getMessage(); . ,6.2 异常处理-捕获异常,finally语句 捕获异常的最后一步是通过finally语句为异常处理提供一个统一的出口,使得在控制流程转到程序的其他部分以前,能够对程序的状态作统一的管理。 无论try所指定的程序块中是否抛出异常,也无论catch语句的异常类型是否与所抛弃的异常的类型一致,finally所指定的代码都要被执行,它提供了统一的出口。 通常在finally语句中可以进行资源的清除工作,如关闭打开的文件、删除临时文件等。,try in = new FileInputStream(“file1.txt”); 对文件进行处理的程序; catch(IOException e) /对文件异常进行处理; finally /不论是否发生异常,都关闭文件; ,finally在文件处理时非常有用,异常的覆盖 finally代码段中应该把可能产生异常的语句用try-catch保护起来,if (in != null) try in.close(); catch (IOException e) ,/ 使用try-catch结构,防止finally代码段抛出异常,6.2.3 throw和throws语句 如果在一个方法中生成了异常,但是该方法并不处理它产生的异常,而是沿着调用层次向上传递,交由调用它的方法来处理这些异常,这就是声明异常。 通常的情况是在该方法中并不确切知道改如何对这些异常进行处理,比如FileNotFoundException类异常,它由FileInputStream的构造方法产生,但在其构造方法中并不清楚如何处理它,是终止程序的执行还是新生成一个文件,这需要由调用它的方法来处理。,6.2 异常处理,声明异常的方法 声明异常的方法是在产生异常的方法名后面加上要抛出(throws)的异常的列表: retType methodName(paramlist) throws exceptionList 如类FileInputStream中的read()方法是这样定义的: public int read() throws IOException throws子句中可以同时指明多个异常,说明该方法将不对这些异常进行处理,而是声明抛弃它们。 需要强调的是:对于非运行时异常,程序中必须要作处理,或者捕获,或者声明抛弃;而对于运行时异常,程序中则可不处理。,6.2 异常处理,public void method1() int x; try x = System.in.read(); compute(x); catch(IOException ioe) System.out.println(“read error”); catch(ArithmeticException e) System.out.println(“devided by 0”); ,public int compute(int x) throws ArithmeticException int z = 100/x; return z; ,调用,非运行时异常 Throwable、Exception 运行时异常 Error、RuntimeException 当在一个方法的代码中抛出一个受检查的异常时,这个异常或者被方法中的try-catch结构捕获,或者在方法的throws语句中声明 编译器检查程序,保证所有非运行时异常都被程序显式地处理,6.2 异常处理,6.2 异常处理,声明异常首先必须生成异常。前面所提到的异常或者是由Java虚拟机生成,或者是由Java类库中的某些类生成。事实上,我们在程序中也可以生成自己的异常对象,也即是异常可以不是出错产生,而是人为地抛出。 不论那种方式,生成异常对象都是通过throw语句实现: throw new ThrowableObject(); ArithmeticException e = new ArithmeticException(); throw e; 注意:抛出的异常必须是Throwable或其子类的实例。,任何从Throwable派生的类都可以用throw语句抛出,抛出异常用来表明程序遇到的错误无法正常执行而需要异常处理 throw new MyException(“some infomation”); 异常可以由try代码段中的语句抛出 也可以从被try代码段中调用的方法中抛出 异常还可能产生于数组下标越界以及Java虚拟机内部错误等 Exception和Error是Throwable的直接派生类 Exception,程序应该处理的异常 Error代表系统严重错误,一般程序不处理这类错误 异常抛出点后的代码在抛出异常后不再执行 也可以说异常的抛出终止了代码段的执行,6.2 异常处理,6.3 自定义异常处理类,当我们在设计自己的类包时,应尽最大的努力为用户提供最好的服务,并且希望用户不要滥用我们所提供的方法,当程序出现某些异常事件时,我们希望程序足够健壮以从程序中恢复,这时就需要用到异常。在选择异常类型时,可以使用Java类库中已经定义好的类,也可以自己定义异常类。自定义异常类不是由Java系统监测到的异常(如数组下标越界,被0除等),而是由用户自己定义的异常。 自定义异常同样要用try-catch-finally捕获,但必须由用户自己抛出(throw)。,异常是一个类,自定义异常必须继承自Throwable或Exception类。建议: 异常一定是不经常发生的故障,应避免把控制流程作为异常处理 尽量使用JDK提供的异常类:重用、便于理解 用Exception/ RuntimeException类:编译时异常、运行时异常。 一般不把自定义异常作为Error的子类,因为Error通常被用来表示系统内部的严重故障。,6.3 自定义异常处理类,当自定义异常是从RuntimeException及其子类继承而来时,该自定义异常是运行时异常,程序中可以不捕获并处理它。 当自定义异常是从Throwable、Exception及其其他子类继承而来时,该自定义异常是编译时异常,也即程序中必须捕获并处理它。 自定义异常的形式: class MyException extends Exception ,6.3 自定义异常处理类,例1:计算两个数之和,当任意一个数超出范围时,抛出自己的异常。,public class NumberRangeException extends Exception public NumberRangeException(String msg) super(msg); ,public int CalcAnswer(String str1, String str2) throws NumberRangeException int int1, int2; int answer = -1; try int1 = Integer.parseInt(str1); int2 = Integer.parseInt(str2); if( (int1 20) | (int2 20) ) NumberRangeException e = new NumberRangeException (“Numbers not within the specified range.“); throw e; answer = int1 + int2; catch (NumberFormatException e) System.out.println( e.toString() ); return answer; ,public void getAnswer() String answerStr; try int answer = CalcAnswer(“12”, “5”); answerStr = String.valueOf(answer); catch (NumberRangeException e) answerStr = e.getMessage(); System.out.println(answerStr); ,6.3 自定义异常处理类,例2:在定义银行类时,若取钱数大于余额则作为异常处理(InsufficientFundsException)。 思路: 产生异常的条件是余额少于取额,因此是否抛出异常要先判断该条件。 确定产生异常的方法,应该在取钱方法(withdrawal)中产生异常InsufficientFundsException 。 处理异常安排在调用withdrawal的时候,因此withdrawal方法要声明异常,由上级方法捕获并处理。 要定义好自己的异常。,public class InsufficientFundsException extends Exception private Bank excepbank; private double excepAmount; InsufficientFundsException(Bank ba, double dAmount) excepbank = ba; excepAmount = dAmount; public String excepMesagge() String str = “The balance” + excepbank.getbalance() + “The withdrawal was”+excepAmount; return str; ,class Bank double balance; /余额 Bank(double b) balance = b; public void deposite(double dAmount) /存钱 if(dAmount0.0) balance += dAmount; public void withdrawal(double dAmount) throws InsufficientFundsException if( balancedAmout ) throw new InsufficientFundsException(this, dAmount); balance = balance-dAmount; public double getbalance() /获取余额 return balance; ,public class ExceptionDemo public static void main(String args) try Bank ba = new Bank(50); ba.withdrawal(100); System.out.println(“Withdrawal succ

温馨提示

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

评论

0/150

提交评论