《异常处理》PPT课件.ppt

上传人:本田雅阁 文档编号:2768018 上传时间:2019-05-12 格式:PPT 页数:67 大小:242.01KB
返回 下载 相关 举报
《异常处理》PPT课件.ppt_第1页
第1页 / 共67页
《异常处理》PPT课件.ppt_第2页
第2页 / 共67页
《异常处理》PPT课件.ppt_第3页
第3页 / 共67页
《异常处理》PPT课件.ppt_第4页
第4页 / 共67页
《异常处理》PPT课件.ppt_第5页
第5页 / 共67页
点击查看更多>>
资源描述

《《异常处理》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《异常处理》PPT课件.ppt(67页珍藏版)》请在三一文库上搜索。

1、1,第八章 异常处理(Exception),8.1 异常分类 8.2 引发异常 8.3 声明抛出异常 8.4 捕捉异常 8.5 定义自己的异常类型 8.6 构造方法与异常处理 8.7 小结,2,try-catch-finally语句 ,其语法格式: try /可能发生异常的代码 catch(异常类型1 变量) /异常的处理代码 catch(异常类型2 变量) /异常的处理代码 . finally /总是要执行的代码 ,3,异常(例外) 是方法代码运行时出现的非正常状态,这种非正常状态使程序无法或不能再正常地继续往下运行。 常见的异常: 数组下标越界 除数为零 内存溢出 文件找不到等。,4,运行

2、机制: 当一个方法在运行时发生异常时,将产生相应类型的一个异常对象、中止代码继续往下运行并寻找相应的异常处理代码。 异常处理: 1 判断异常类型 2 产生对象 3 捕获处理异常,5,异常对象记录着这个异常的一些描述和状态信息。 方法运行失败时,记录这个异常信息的异常对象将产生(或称为引发,抛出,throw),它有两种引发方式: 1 系统自动引发 2 在程序中由throw语句引发 异常对象引发后,系统根据异常对象的类型,首先在当前方法寻找相应的异常处理代码,找到后就将控制流转入该异常处理代码并向其传递异常对象(称为捕获该异常,catch),异常处理代码可以根据接受到的异常对象进行相应的处理;,6

3、,寻找相应的异常处理代码的过程:,当前方法 直接或间接调用者 找到,传递异常对象并进行异常处理 没有找到,调用默认的异常处理程序,中止当前线程,7,举例(没有异常处理的情况),1) class ExceptionDivideBy0 2) static void method() int x = 0, z=10; int y = 10 / x; System.out.println(“z=“+z); public static void main(String args) method(); System.out.println(“After method.“); 11) ,8,Exceptio

4、n in thread “main“ java.lang.ArithmeticException: / by zero at ExceptionDivideBy0.method(ExceptionDivideBy0.java:4) at ExceptionDivideBy0.main(ExceptionDivideBy0.java:8) Press any key to continue.,9,具有异常处理的情况,class ExceptionDivideBy0 static void method() int x = 0,z=10; try int y = 10 / x; System.ou

5、t.println(“z=“+z); catch(ArithmeticException e) System.out.println(“ArithmeticException“); System.out.println(“After try/catch blocks.“); public static void main(String args) method(); System.out.println(“After method.“); ,10,ArithmeticException After try/catch blocks. After method.,11,每个异常由类Throwab

6、le或者它的一个子类的实例表示,这样的对象可被抛出并能被传递给合适的异常处理代码处理。Throwable类及其子类统称为异常类,每个异常类表示一种异常类型。 Throwable类是Object类的直接子类,其本身又有两个直接子类: Error与Exception类。RuntimeException类是Exception类的直接子类,如图8-1所示。这里, Error类、RuntimeException类和Exception类分别代表某一类异常类型:,8.1 异常分类,12,图8-1 异常类型及其分类,13,(1) Error类及其子类: 表示灾难性的、普通程序很难恢复的异常,例如: NoCla

7、ssDefFoundError(类定义没找到异常): JVM无法找到相应的class文件。 OutOfMemoryError(内存越界异常): JVM没有足够的存储空间满足对象创建的要求。 NoSuchMethodError(调用不存在的方法异常): 在改变某个方法的签名后,原先要调用该方法的应用程序,在运行时就会抛出该异常。 一般情况下,程序员可不必理会这类异常,它们虽然很严重,但很少发生。,14,(2) RuntimeException类及其子类: 表示设计或实现方面的问题,例如: ArithmeticException(算术运算异常): 算术运算时发生的异常情况,如整数相除,除数为零。

8、ClassCastException(强制类型转换异常): 把一个对象引用转换成一个不合适的类型,如把一个对象引用转换成某个子类类型。 NullPointerException(空引用异常): 需要对象引用时使用了一个null引用。 ArrayIndexOutOfBoundsException(数组下标越界异常): 下标值超出了数组大小。 NumberFormatException(数字格式异常): 试图将非数字格式字符串转换成数值。,15,(3) Exception类及其非RuntimeException子类: 表示运行时因环境的影响而引发的异常,例如: IOException(输入输出异常

9、): 在I/O操作失败或者被中断时引发。其子类包括: EOFException、FileNotFoundException、InterruptedIOException等。 InterruptedException(中断异常): 当前等待或睡眠线程被其他线程中断时引发。 这类异常并非因设计或实现引起,是无法避免的。但一般情况下,程序员应该提供相应的代码捕捉和处理。,16,受检查的异常和不受检查的异常: 受检查的异常 Exception类及其非RuntimeException子类属于受检查的异常; 受检查的异常要受编译系统的检查。如果一个方法可能会引发这类异常而又不能适当处理,那么应该用thro

10、ws子句声明抛出;调用者或者用try-catch语句捕捉处理,或者也用throws子句声明抛出,并由它的调用者处理。 也就是说,对方法中可能会抛出的受检查异常,程序员必须捕捉处理或声明抛出,两者必选其一,否则编译系统将给出错误信息。,17,受检查的异常和不受检查的异常: 不受检查的异常: 类Error和类RuntimeException及其子类属于不受检查的异常,如图8-1所示。 不受检查的异常不受编译系统的检查。对这类异常,程序员可以捕捉或声明抛出,但通常可以不加理会。,18,异常类的方法和属性,(1)异常类的构造方法 public Exception() 创建新异常。 public Exc

11、eption(String message) 用字符串参数message描述异常信息创建新异常。 (2)异常类的方法 public String toString() 返回描述当前异常对象信息的字符串。 public String getMessage() 返回描述当前异常对象的详细信息。 public void printStackTrace() 在屏幕上输出当前异常对象使用堆栈的轨迹,即程序中先后调用了哪些方法,使得运行过程中产生了这个异常对象。,19,所谓异常的引发是指因程序运行出现异常情况而产生异常对象、进而转入异常处理过程的情形。Java运行系统在发现异常情况时会自动引发异常。 自动

12、引发异常 如下例:,8.2 引发异常,20,【例8-1】在发生异常情况时由运行系统引发异常 class Demo public static void main(String args) int a = args.length; System.out.println(“a = “ + a); int b = 42 / a; int c= 1 ; c4 = 99; System.out.println(“After try/catch blocks.“); ,21,throw引发异常 异常既可以在发生异常情况时由运行系统引发,也可以在程序中用throw语句显式引发。 格式如下: throw ne

13、w ArithmeticException();,22,【例8-2】下面程序在被减数a小于减数b时将引发ArithmeticException异常。 1) class Test 2) static int method(int a,int b) 3) if(a b) 4) throw new ArithmeticException(“a b“); /产生异常 5) return a - b; 6) 7) public static void main(String args) 8) method(3, 5); 9) 10) ,下面是该程序的输出结果: Exception in thread “

14、main“ java.lang.ArithmeticException: a b at Test.method(Test.java:4) at Test.main(Test.java:8),23,如果一个方法引发的是受检查的异常且自己没有捕捉,那么它必须用throws子句声明抛出; 该方法的调用者如果不对异常进行捕捉,那么也必须用throws子句声明抛出。 下面是包含throws子句的方法定义的语法格式: () throws .,8.3 声明抛出异常,24,【例8-3】下面程序与例8-2中的程序基本相同,只是method方法可能抛出的是一个受检查的Exception异常,但它既没有捕捉也没有声

15、明抛出,所以是不能通过编译的。 1) class Test 2) static int method(int a,int b) 3) if(a b) 4) throw new Exception(“a b“); 5) return a - b; 6) 7) public static void main(String args) 8) int r = method(3, 5); 9) System.out.println(“r = “ + r); 10) 11) ,throws Exception ,throws Exception ,25,对不受检查的异常,同样可以声明抛出(或进行捕捉),这

16、在语法上是允许的。 无论是受检查的异常还是不受检查的异常,对不受检查的异常,不管是否声明了异常抛出,异常一旦引发,其处理过程是一致的,即: 异常沿着方法调用的反方向传播,寻找并转入合适的异常处理代码执行。如果方法及其所有的调用者都没有提供合适的处理代码,那么异常将最终传播到运行系统,运行系统调用默认的异常处理代码后终止程序执行。图8-2说明了例8-2和例8-3中异常引发和传递的过程。,26,图8-2 异常传播过程示意图,27,回忆超类和子类中方法覆盖的要求: 两个方法具有相同的方法签名(即方法名和方法的参数完全一致) 返回类型相同 覆盖方法的访问级别不能低于被覆盖方法的访问级别 覆盖方法(子类

17、方法)不能比被覆盖方法(超类方法)抛出更多类型的受检查异常。 下面通过例子加以说明。,28,【例8-4】有以下类定义: 1) import java.io.*; 2) 3) class TestClass 4) void testM(BaseClass o) throws IOException 5) o.method(); 7) 8) 9) class BaseClass 10) void method() throws IOException 11) 12) ,29,请问下面哪些BaseClass类的子类定义是合法的? A) class A extends BaseClass void m

18、ethod() throws IOException B) class B extends BaseClass void method() throws Exception C) class C extends BaseClass void method() throws EOFException,FileNotFoundException ,30,D) class D extends BaseClass void method() throws IOException,InterruptedException E) class E extends BaseClass void method(

19、) F) class F extends BaseClass void method() throws IOException,NullPointerException ,31,【例2.10】从键盘输入一个整数和实数,并输出它们的和,import java.io.*; / 引入java.io包 class InputDemo public static void main(String args) throws IOException / 用标准输入System.in创建一个 BufferedReader BufferedReader br = new BufferedReader(new I

20、nputStreamReader(System.in); System.out.print(“请输入一个整数:“); String str = br.readLine(); / 输入字符行存入字符串 int i = Integer.parseInt(str);/ 转换字符串为整型数据,32,System.out.print(“请输入一个实数:“); str = br.readLine(); float f = Float.parseFloat(str); System.out.print(“它们的和是:“+(i+f); ,33,如果不加以捕捉,引发的异常将沿着方法调用的反方向往外抛出和传播,直

21、至Java运行系统。通常,这并不是所希望的结果。一般来说,引发异常的方法的调用者应该捕捉,并根据具体情况处理异常,从而阻止异常继续往外传播。Java使用try-catch-finally语句来捕捉和处理可能发生的异常,该语句的语法格式如下:,8.4 捕捉异常,34,try / 此处是可能发生异常的代码 catch( ) / 异常的处理代码 catch( ) / 异常的处理代码 finally / 总是要执行的代码 该语句包含try、catch和finally三个子句。其中,catch子句可以有多个,而且至少有一个catch子句或finally子句。,35,try子句包含一段可能要发生异常的代码

22、。一旦发生异常,将由后面的catch子句捕捉处理。每个catch子句有一个参数,参数类型指明该子句能够捕捉的异常类型。如果子句指定的参数类型是所发生的异常的类或者是其超类,则说明catch子句能够捕捉该异常。此时,运行系统将把异常对象的引用值传递给catch子句的参数变量,并将控制流转移到该catch子句,执行子句内的异常处理代码。之后,接着执行try语句后面的代码。 如果try子句内的代码没有发生任何异常,那么跳过catch子句,直接执行try语句后面的代码。,8.4.1 try和catch子句,36,class Demo public static void main(String arg

23、s) try int a = args.length; System.out.println(“a = “ + a); int b = 42 / a; int c= 1 ; c4 = 99; catch(ArithmeticException e) / 捕获算术运算异常 System.out.println(“Divide by 0: “ + e); catch(ArrayIndexOutOfBoundsException e) System.out.println(“Array index oob: “ + e); System.out.println(“After try/catch bl

24、ocks.“); ,【例8-5】try和catch子句举例,37,a = 0 Divide by 0: java.lang.ArithmeticException: / by zero After try/catch blocks.,38,最后说明两点: (1) 当发生异常时,如果有catch捕捉到了异常,那么不管具体的异常处理代码如何(甚至不含任何语句),Java运行系统都认为该异常已被消除; (2) 当执行完异常处理代码后,控制流并不会回到异常发生处,而是执行try语句后面的代码(如果没有finally子句)。,39,try子句内的代码可能会发生多种类型的异常,而try语句也允许有多个ca

25、tch子句,每个catch子句可以捕捉一种类型(包括子类型)的异常。 当然,每次执行try语句时,至多只能抛出一个异常,相应地,至多只能有一个异常处理代码被执行。,8.4.2 多个catch子句,40,当异常发生时,运行系统将按先后次序依次判断各catch子句,如果发现某个catch子句能够捕捉该异常,就执行其中的处理代码,而其后面的catch子句将被忽略。 注意:处理子类型异常的catch子句一定要放在处理超类型异常的catch子句之前。 如果将一个处理超类型异常的catch子句放在处理子类型异常的catch子句之前,或者两个catch子句捕捉同一类型的异常,编译系统都将给出错误信息。,41

26、,public class Test2 public static void main (String args) int x=0; int y; try y=100/x; catch (Exception ex) ex.printStackTrace(); catch (ArithmeticException ex) ex.printStackTrace(); ,(ArithmeticException ex),(Exception ex),42,使用finally子句的好处是: 控制流不管以何种原因离开try语句,都要先执行finally子句。 所以,可以将那些无论是否发生异常、异常无论是

27、否被捕捉都需要执行的代码放置在finally子句内。,8.4.3 finally子句,43,控制流离开try语句的情况可分为以下几种: try子句代码正常执行,没有引发异常; try子句代码执行时引发异常,但被catch子句捕捉处理; try子句代码执行时引发异常,但没有catch子句能捕捉处理; try子句代码执行时引发异常,且被catch子句捕捉,但在执行异常处理代码时发生新的异常。 注意:因return、break或continue等跳转语句(不管是出现在try子句中,还是出现在catch子句中)要离开try语句时,同样需要先执行finally子句。,44,1) class Finall

28、yDemo 2) static void m1(int i) 3) try 4) if(i = 2) 5) System.out.println(“第2种情况: 发生算术运算异常“); 6) throw new ArithmeticException(); 7) if(i = 3) 8) System.out.println(“第3种情况: 发生数字格式异常“); 9) throw new NumberFormatException(); 10) if(i = 4) 11) System.out.println(“第4种情况: 发生数组下标越界异常“); 12) throw new Array

29、IndexOutOfBoundsException(); 13) 14) System.out.println(“第1种情况: 没有发生异常“); 15) ,【例8-9】finally子句举例,45,15) catch(ArithmeticException e) 16) System.out.println(“异常被捕捉处理“); 17) catch(ArrayIndexOutOfBoundsException e) 18) System.out.println(“异常被捕捉,但又被重新引发“); 19) throw e; 20) finally 21) System.out.println

30、(“这是finally子句“); 23) System.out.println(“这是try语句后的代码“); 24) 25) public static void main(String args) 26) for(int i = 1; i 5; i+) 27) try 28) m1(i); 29) catch(RuntimeException e) 30) System.out.println(“由main方法捕捉到异常“); ,46,下面是程序的输出结果: 第1种情况:没有发生异常 这是finally子句 这是try语句后的代码 第2种情况:发生算术运算异常 异常被捕捉处理 这是fina

31、lly子句 这是try语句后的代码,47,下面是程序的输出结果(续): 第3种情况:发生数字格式异常 这是finally子句 由main方法捕捉到异常 第4种情况:发生数组下标越界异常 异常被捕捉,但又被重新引发 这是finally子句 由main方法捕捉到异常,48,当try子句发生异常时,如果没有一个catch子句能够捕捉到,则异常从该try语句抛出并向外传播。 如果try语句本身是另外一个try语句的try子句的一部分,那么异常就由该外层try语句的catch子句捕捉处理。 如果没有外层的try语句,或者外层try语句也没有catch子句能够捕捉该异常,则异常被传播到方法的调用者那里,由

32、调用方法处理。,8.4.4 未捕捉到的异常,49,1) class Test /例8-7未捕捉到的异常被传播并由调用方法捕捉。 2) static void m1(String s) 3) try 4) int x = Integer.parseInt(s); 5) int y = 10 / x; 6) catch(NumberFormatException e) 7) System.out.println(“caught “ + e + “ in m1“); 8) System.out.println(“exiting from m1“); 9) 10) public static void

33、 main(String args) 11) try 12) m1(args0); 13) catch(ArrayIndexOutOfBoundsException e) 14) System.out.println(“caught “ + e + “ in main“); 15) catch(ArithmeticException e) 16) System.out.println(“caught “ + e + “ in main“); 17) System.out.println(“exiting from main“); 18) ,50,该程序可以在不同情况下发生3种不同类型的异常。如

34、果命令行不提供参数,下面是程序的输出结果: C:java Test caught java.lang.ArrayIndexOutOfBoundsException: 0 in main exiting from main 如果命令行的第1个参数为非数字格式字符串,下面是程序的输出结果: C:java Test aaa caught java.lang.NumberFormatException: aaa in m1 exiting from m1 exiting from main 如果命令行的第一个参数为数字0,下面是程序的输出结果: C: java Test 0 caught java.l

35、ang.ArithmeticException: / by zero in main exiting from main,51,try子句发生的异常可以由语句中的某个catch子句捕捉处理,但在执行catch子句内的异常处理代码时也可能再引发新的异常。此时,原先的异常被遗弃,新的异常从try语句抛出并向外传播。与“未捕捉到的异常“类似,该新异常或者由外层try语句的catch子句捕捉,或者由方法的调用者处理。,8.4.5 再引发异常,52,1) import java.io.IOException; /【例8-8】再引发异常举例 2) class Test 3) static void m1(

36、) throws IOException 4) try 5) throw new RuntimeException(“demo_1“); 6) catch(RuntimeException e) 7) System.out.println(“caught “ + e + “ in m1“); 8) throw new IOException(“demo_2“); 9) 10) public static void main(String args) 11) try 12) m1(); 13) catch(IOException e) 14) System.out.println(“caught

37、 “ + e + “ in main“); 15) System.out.println(“exiting from main“); 16) 17),53,下面是程序的输出结果: caught java.lang.RuntimeException: demo_1 in m1 caught java.io.IOException: demo_2 in main exiting from main,54,8.5 定义自己的异常类型 自定义的异常类型必须是Throwable类的子类。只有Throwable类及其子类的实例才能够被引发和捕捉。 通常将自定义异常类型定义成Exception的子类,以产生

38、受检查的异常。 Java异常处理机制的特点是方法的调用者必须认识和处理方法可能会抛出的受检查异常,而对不受检查的异常,调用者则可以不加理会。,55,例:在定义银行类时,若取钱数大于余额则作为异常处理(InsufficientFundsException)。 思路: 产生异常的条件是余额少于取额,因此是否抛出异常要先判断该条件。 确定产生异常的方法,应该在取钱方法withdrawal中产生异常InsufficientFundsException 。 处理异常安排在调用withdrawal的时候,因此withdrawal方法要声明异常,由上级方法捕获并处理。 要定义好自己的异异常。,56,publ

39、ic class InsufficientFundsException extends Exception private Bank excepbank; private double excepAmount; InsufficientFundsException(Bank ba, double dAmount) excepbank = ba; excepAmount = dAmount; public String toString() String str = “The balance“ + excepbank.getbalance() + “The withdrawal was“+exc

40、epAmount; return str; ,57,class Bank double balance; /余额 public void deposite(double dAmount) /存钱 if(dAmount0.0) balance = balance + dAmount; public void withdrawal(double dAmount) throws InsufficientFundsException /取钱 if( balancedAmout ) throw new InsufficientFundsException(this, dAmount); balance

41、= balance-dAmount; public double getbalance() /获取余额 return balance; ,58,public class ExceptionDemo public static void main(String args) try Bank ba = new Bank(); ba.deposite(50); ba.withdrawal(100); System.out.println(“Withdrawal successful!“); catch(Exception e) System.out.println(e.toString(); ,59

42、,【例】设计自己的异常。从键盘输入一个double类型的数,若不小于0.0,则输出它的平方根,若小于0.0,则输出提示信息“输入错误!“。 import java.io.*; class MyException extends Exception double x; MyException(double x) this.x=x; public String toString() return “输入错误:x0.0“+“ x=“+x; ,60,public class MySqrt static void test(double x) throws MyException if(x 0.0) t

43、hrow new MyException(x); else System.out.println(Math.sqrt(x); public static void main(String args) throws IOException try System.out.print(“求输入实数的平方根,请输入一个实数:“); BufferedReader br = new BufferedReader(new InputStreamReader(System.in); String s = br.readLine(); test(Double.parseDouble(s); catch(MyEx

44、ceptionClass e) System.out.println(e.toString(); ,61,与普通方法一样,构造方法也可以引发异常、捕捉异常或者声明抛出异常。实际上,构造方法有时比普通方法更需要使用异常处理机制。对于普通方法,有时可以通过返回一个特殊值来表示其执行出现了异常。例如,一个方法的返回类型是一种引用类型,且在正常情况下它总是能返回一个对象的引用,那么就可以返回一个null值表示非正常情况,而不是抛出异常。这种处理方式不适用于构造方法。构造方法没有返回类型,构造方法体不能使用带表达式的return语句。下面是构造方法引发和抛出异常的一个例子:,8.6 构造方法与异常处理,

45、62,1) class TimeException extends Exception 2) private int t,m,s; 3) TimeException(int t, int m, int s) 4) this.t = t; 5) this.m = m; 6) this.s = s; 7) 8) public String toString() 9) return “Exception“ + t + “,“ + m + “,“ + s + “; 10) 11) 12) 13) public class MyTime 14) private int hour; /023 15) pr

46、ivate int minute; /059 16) private int second; /059,63,18) public MyTime(int h,int m,int s) throws TimeException 19) if(h =24 | m = 60 | s = 60) 20) throw new TimeException(h,m,s); 21) 22) hour = h; 23) minute = m; 24) second = s; 25) 26) 27) 当用new运算符调用构造方法创建类的实例时,如果构造方法抛出异常而突然结束,那么对象的引用值不会被返回。例如: M

47、yTime t; t = new MyTime(11,69,10);,64,(1) 异常是方法代码运行时出现的非正常状态,这种非正常状态使程序无法或不能再正常地继续往下运行。 (2) Java采用面向对象的方法来处理异常。每当发生异常事件时,就会引发一个异常对象。运行系统根据异常对象的类型寻找相应的代码处理异常。异常对象的类型是Throwable类或其子类。 (3) Java编译系统将异常分为受检查的异常(unchecked Exceptions)和不受检查的异常(checked Exceptions)两大类。,8.7 小结,65,(4) 异常引发方式:由运行系统引发,由throw语句显式地引发。 (5) 异常引发时,代码将不再继续往下执行,而由系统寻找合适的异常处理代码执行。当不能寻找到合适的异常处理代码时,将调用默认异常处理程序,并终止当前线程。 (6) 对不受检查的异常,Java程序

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

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1