第14讲 异常处理 1/.

Slides:



Advertisements
Similar presentations
软件编程基础 一、程序的编辑 Java 源程序是以 Java 为后缀的简单的文本文件,可以用各种 Java 集成开发环境中的源代码编辑器来编写,也可以用其他文 本编辑工具,如 Windows 中的记事本或 DOS 中的 EDIT 软件等。 利用文字编辑器编写下列程序 public class Hello.
Advertisements

第 7 章 异常处理. 立体化教材计算机系列 — 《 Java 程序设计》 2 目 录 重点与难点点拨 经典练习题 异常处理机制 异常.
面向侧面的程序设计 方林博士 本文下载地址:
第四章 类、对象和接口.
3.2 Java的类 Java 类库的概念 语言规则——程序的书写规范 Java语言 类库——已有的有特定功能的Java程序模块
Java的程式架構與基本觀念 Java語言的歷史 Java程式的開發環境 Java程式的架構 輸出與輸入物件之使用 工具使用方法介紹
四資二甲 第三週作業 物件導向程式設計.
Exception子类的继承关系 Exception ClassNotFoundException
Java程序设计 第6章 异 常 处 理.
第二章 JAVA语言基础.
第14章 c++中的代码重用.
在PHP和MYSQL中实现完美的中文显示
第10讲 Java面向对象编程基础(4) 教学目标 主要内容.
第三章 控制结构.
第九章 字符串.
程式設計實作.
第5章 异常处理 王德俊 上海交通大学继续教育学院.
2.1 基本資料型別 2.2 變數 2.3 運算式與運算子 2.4 輸出與輸入資料 2.5 資料型別轉換 2.6 實例
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
例外處理(Exception Handling)
Java基础 JavaSE异常.
第七章 异常.
JAVA 编 程 技 术 主编 贾振华 2010年1月.
西南科技大学网络教育系列课程 高级语程序设计(Java) 第五章 继承、接口与范型.
欢乐玩转单元测试之JUnit 讲师:FREE QQ:
程式設計實作.
第 14 章 例外處理.
Java语言程序设计 第五部分 Java异常处理.
第6章 异常的捕获及处理 6.1 异常简介 6.2 异常类的继承结构 6.3 异常处理机制 6.4 异常处理 6.5 本章小结.
Java习题解析.
王豐緒 銘傳大學資訊工程學系 問題:JAVA 物件檔輸出入.
第三章 流程控制與例外處理 資訊教育研究室 製作 注意:本投影片僅供上課使用,非經同意,請勿散播或轉載。
辅导课程六.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
第5章 异常处理 王德俊 上海交通大学继续教育学院.
9.1 程式偵錯 9.2 捕捉例外 9.3 自行拋出例外 9.4 自定例外類別 9.5 多執行緒
异常及处理.
C/C++/Java 哪些值不是头等程序对象
用event class 从input的root文件中,由DmpDataBuffer::ReadObject读取数据的问题
第4章 PHP流程控制语句.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
$9 泛型基础.
第7章 异常处理.
第二章 Java基本语法 讲师:复凡.
第12章 异常处理 C++自身有着非常强的纠错能力,发展到如今,已经建立了比较完善的异常处理机制. C++的异常情况无非两种,一种是语法错误,即程序中出现了错误的语句、函数结构和类,致使编译程序无法进行。另一种是运行时发生的错误,一般与算法有关。 关于语法错误, C++编译器的报错机制可以让我们轻松地解决这些错误;
Java程式初體驗大綱 大綱 在學程式之前及本書常用名詞解釋 Hello Java!程式 在Dos下編譯、執行程式
本节内容 类成员的访问控制 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
第二章 Java语法基础.
3.16 枚举算法及其程序实现 ——数组的作用.
Chapter 18 使用GRASP的对象设计示例.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
辅导课程十五.
第二章 Java基本语法 讲师:复凡.
第二章 Java基本语法 讲师:复凡.
本节内容 C语言的汇编表示 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
Java程序设计 第17章 异常和断言.
C++语言程序设计 C++语言程序设计 第十一章 异常处理 C++语言程序设计.
基于列存储的RDF数据管理 朱敏
3.7 Java的异常处理机制.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
JAVA 程式設計與資料結構 第三章 物件的設計.
第2章 Java语言基础.
第6章 异常处理 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
创建、启动和关闭Activity 本讲大纲: 1、创建Activity 2、配置Activity 3、启动和关闭Activity
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
第二章 Java基础语法 北京传智播客教育
輸出執行結果到螢幕上 如果要將執行結果的文字和數值都「輸出」到電腦螢幕時,程式要怎麼寫? class 類別名稱 {
第二章 Java基本语法 讲师:复凡.
Presentation transcript:

第14讲 异常处理 1/

教学目标 理解Java异常处理机制原理 掌握捕获与处理异常方法 掌握Java自定义异常及处理特殊异常的方法

引例 public class Ex8_1{ public static void main (String args[]) {   int i = 0;   String greetings [] = { “Hello world!”, “No, I mean it!”, “HELLO WORLD!!”};   while (i < 4) {    System.out.println (greetings[i]);    i++;   }  } } 运行结果: Hello world! No, I mean it! HELLO WORLD!! Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 at Ex8_1.main(Ex8_1.java:9)

引例分析 从上述例题可以发现,在Java语言中,并不是所有程序都是完美的和不会发生运行时错误的,我们将程序运行时发生的错误叫做异常。下面任何一种情况都会出现异常: 想打开的文件不存在; 在访问数组时,数组的下标值超过了数组允许的范围; 整除时除数为0; 正在装载的类文件丢失。

异常机制的作用 Java中的每个异常类都代表了一种运行错误,每当Java程序运行过程中发生一个可识别的运行错误时,系统都会产生一个相应的该异常类的对象,即产生一个异常。一旦一个异常对象产生了,系统中就一定有相应的机制来处理它,确保不会产生死机、死循环或其他对操作系统的损害,从而保证了整个程序运行的安全性,这就是Java的异常处理机制。 在没有异常处理的语言中,必须使用if-else或switch等语句,捕捉程序中所有可能发生的错误情况。Java的异常处理机制恰好弥补这个不足,它具有易于使用、可自定义异常类、允许抛出异常且不会降低运行速度等优点。因而在设计Java程序时,充分利用Java异常处理机制,可大大提高程序的稳定性及效率。

异常和异常类 作为面向对象语言,异常与其他语言要素一样,是面向对象范围的一部分,是异常类的对象。Java所有的异常对象都是继承Throwable类的实例,Throwable类是类库java.lang包中的一个类,它派生了两个子类:Error类和Exception类。如图8-1所示。 Error类被认为是不能恢复的严重错误,如系统内部错误、资源耗尽错误等。由于在些种情况下,除了通知用户并试图终止程序外几乎是不能做其他任何处理的,因此,不应该抛出这种类型的错误,而是直接让程序中断。 Exception类定义可能遇到的轻微错误,分为继承RuntimeException类的异常和非继承RuntimeException类的异常。这时,可以写代码来处理异常并继续程序执行,而不是让程序中断。

异常和异常类 图8-1 Java异常继承关系示意图

异常处理 引例中,异常发生后,Java在运行时将这个异常抛出,可是抛出后没有程序代码去捕捉它,所以程序被中断。 如果添加捕捉异常的程序代码,则可针对不同的异常做妥善的处理。 try{} catch(){} finally{}

异常处理示例 public static void main (String args[]) { int i = 0; String greetings [] = {“Hello world!”, “No, I mean it!”, "HELLO WORLD!!“ }; while (i < 4) {  try {System.out.println (greetings[i]); //可能出现数组越界异常的代码}  catch (ArrayIndexOutOfBoundsException e){ //数组越界的异常处理  System.out.println( "Re-setting Index Value");  i = -1;  }  finally {    System.out.println(“This is always printed”); //始终在循环过程       i++; } 运行结果: Hello world! This is always printed No, I mean it! HELLO WORLD!! Re-setting Index Value

异常处理方法 通过上例发现,当一个方法被调用时如果发生异常,必须采取相应措施解决出现的问题,即进行异常处理。有两种方法解决以上问题。 第一,通过try-catch语句捕获异常,并调用方法处理它。 第二,被调用的方法自己不处理异常,该异常将被抛回到调用它的方法中。它是使用throws来实现的,例如,public void troublesome() throws IOException 关键字throws之后是troublesome()出现的所有异常列表,该方法可以抛回IOException到调用它的程序中。如果有多个异常被抛出,可以使用逗号分开的列表列出所有的异常类。 声明异常

声明异常示例 运行结果: import java.io.*; C:\java>java Ex8_3 求平方根: 4 2.0 -4 输入的数是负数,不能求平方根 import java.io.*; class Ex8_3 extends Exception{  void test(double x) throws Ex8_3{ //声明异常   if(x < 0.0) throw new Ex8_3 ();   else System.out.println(Math.sqrt(x));  }  public static void main(String args[]) throws IOException{   Ex8_3 me = new Ex8_3 ();   try{    System.out.println("求平方根: ");    BufferedReader input = new BufferedReader(new InputStreamReader(System.in));    String str = input.readLine();    me.test(Double.parseDouble(str));   }catch(Ex8_3 e){    System.out.println("输入的数是负数,不能求平方根");   } } 程序分析:在这个程序中,定义的异常类继承了Exception异常类。在test()方法首部声明了异常Ex8_3异常,并在其方法中用throw子句指定了可能抛出的异常。

捕获异常 通过例8.2可知异常的捕获和处理是由try、catch和finally所组成的程序块完成的,我们先探讨try-catch语句块,其格式如下: try{ 可能产生异常的代码 //try块 } catch (ExceptionType e1 ){ //要捕获的异常类型 对此异常的处理 //异常处理,可以为空 }…… catch(ExceptionType en ){ } 异常的捕获和处理流程如下: 1. 如果try块中没有代码产生异常,那么程序将跳过catch子句 2. try块中的任意代码产生一个属于catch子句所声明类的异常,程序将跳过try块中的剩余代码,并执行与所产生异常类型匹配的catch子句的异常处理代码。 3. 如果try块中的代码产生一个不属于所有catch子句所声明类的异常,那么该方法会立即退出。

捕获异常(续) 这种方式将所有的代码都置入一个try块内集中处理,因此大量不同的方法调用可能生成相同的异常,只需要一个控制器就可以捕获处理。当然,如果自己捕获并处理异常,就不用在方法头部用throws语句来声明异常了。 我们已经知道,当异常产生时,方法的执行流程非线性方式执行,甚至在没有匹配catch子句时,可能从方法中过早退出。但有时,无论异常发生还是被捕获,都希望有些语句必须执行。例如,首先要打开文件,接着对文件进行处理,然后关闭文件,当然不希望将关闭文件的这段代码由异常处理来进行。finally语句就提供了这种问题的解决办法

重新抛出异常 Graphics g = image.getGraphics(); try{ 可能产生异常的代码 //try块 } catch(MalformedURLException e){ System.out.println("an MalformedURLException!!"); g.dispose();  //释放对象g throw e ; //重新抛出异常e 当出现异常时,try块里的剩余代码都不会被执行,那么对象g将一直被保持,直到它的finalize方法释放它(占用内存),因此当不知道如何处理此异常时,在产生此异常之前需要对本地资源进行清理,如在catch子句里释放对象g,然后抛出已经捕获的异常。这就是重新抛出异常的最常见的原因。

finally子句 但是这种方法比较烦琐,因为在try块的正常代码里也必须要清除本地对象,清除对象的代码将出现在两个地方,一个在try块里,一个在catch子句里。当有多个catch子句时,每个子句都要清除对象。为解决这种重复性,Java提供了finally子句。 Graphics g = image.getGraphics(); try{ 可能产生异常的代码 //try块 } catch(MalformedURLException e){ System.out.println("an MalformedURLException!!!“); finally{ g.dispose(); //释放对象g

finally子句(续) finally子句是必须执行的,无论程序是否捕获到异常。当程序中出现finally子句时,执行流程分四种情况: 1. 方法不抛出任何异常。程序将执行try块里的所有代码,然后执行finally子句的代码,再执行后续代码。 2. 方法抛出catch子句能够捕获的异常,而且catch子句没有重新抛出异常。此时,程序将执行try块中的代码,直到抛出异常,然后try块的剩余代码被跳过,执行匹配的catch子句代码,接着执行finally子句的代码,再执行后续代码 3. 方法抛出catch子句能够捕获的异常,而且catch子句重新抛出异常。执行过程与第2种情况相同,只是最后异常被重新抛出。 4. 方法抛出不能被catch子句捕获的异常。此时,程序先执行try块里的代码,直到抛出异常,然后跳过try块的剩余代码,执行finally子句的代码,再将异常抛出给该方法的调用者。

抛出异常 Java程序在运行时如果引发了一个可以识别的错误,就会产生一个与该错误相对应的异常类的对象,这个过程称作异常的抛出,实际是相应异常类的实例的抛出。根据异常类的不同,抛出异常的方式也有所不同 系统自动抛出的异常——所有的系统定义的运行错误异常 语句抛出的异常 用户自定义的异常不可能依靠系统自动抛出,必须用throw语句明确地抛出一个异常。首先,必须知道什么情况下产生了某种异常对应的错误,然后为这个异常类创建一个实例,最后用throw语句抛出。下面是throw语句的常用格式: 返回类型 方法名(参数列表)throws 要抛出的异常类名列表{ …… throw 异常实例; …… }

抛出异常(续) 这样定义方法后,可通知所有要调用这个方法的上层方法,准备接受和处理它在运行中可能会抛出的异常。 一般情况下,这种抛出语句应在某种条件满足下执行,例如, void MyMethod()throws MyException{ //可能在程序中抛出MyException异常 …… if(i>100) throw(new MyException()); } 如果方法中的throw语句不止一个,则应该在方法头throws后列出所有可能的异常。

抛出异常(续) 若某个方法MyMethod可能产生Exception1、Exception2和Exception3 三种异常,而它们又都是Super_Exception类的子类,则应在相应的方法中声明可能抛出的异常类,语句如下: void MyMethod() throws Exception1,Exception2,Exception3 { …… //可能抛出这三个异常 } 还可以只简单地声明抛出Super_Exception,下面这种方式和上面的是等价的。 void MyMethod() throws Super_Exception{ ……//可能抛出这三个异常的父类

抛出异常(续) 在Java语言中如果调用了一个可能产生异常的方法,如果调用方法不处理这个异常,则在调用方法中要对这个异常类进行声明,如下面代码: void YourMethod() throws Super_Exception{ …… MyMethod();//调用了可能会抛出异常的方法 } Java语言要求所有用throws关键字声明的类和用throw抛出的对象必须是Throwable类或其子类。但如果试图抛出一个不可抛出的异常,Java编译器将会报错。

抛出异常-重新抛出异常 重新抛出异常  前面说过,被调用方法自己可以不处理异常,只是在方法头部简单声明(声明异常),由调用方法决定如何处理异常,或者也可以在被调用方法中捕获异常并进行处理。那么该不该捕获异常,有何规则?一般来说,捕获知道如何处理的异常,对于不知道如何处理的异常则进行声明,告诉调用方法,一个异常可能会被抛出。需要进行下一步处理的异常采用重新抛出异常的方法。

重新抛出异常示例 // 一个重新抛出异常的示例 public class Ex8_4 {  public static void found() throws Exception{  System.out.println("the original exception in found()");  throw new Exception("thrown from found()");  }  public static void main(String args[]) throws Exception{  try{ found(); }   catch(Exception e){ System.out.println(“catch in main()"); throw e; } } 运行结果: the original exception in found() catch in main() Exception in thread "mian" thrown from found() at Ex8_3.found(Ex8_3.java:4) at Ex8_3.main(Ex8_3.java:7)

自定义异常 为了适应各种异常,Java语言可以通过继承的方式编写自己的异常类。因为所有的异常类均继承自Exception类,所以自定义类也必须继承这个类。自定义异常类的语法如下, class 异常类名 extends Exception { 类体 } 在自定义异常类里通过编写新的方法来处理相关的异常,甚至可以不编写任何语句也可正常工作,因为Exception类已提供相当丰富的方法。

自定义异常示例 程序分析:异常类和普通类一样,可以有成员变量、方法,能对变量进行操作。同系统异常一样,可使用throw语句来抛出自定义异常。 // 创建自己的异常类。 public class Ex8_5 extends Exception {  private String reason;  private int port;  public Ex8_5 (String reason,int port){   this.reason = reason;   this.port = port;  }  public String getReason() {   return reason;  public int getPort() {   return port; } 程序分析:异常类和普通类一样,可以有成员变量、方法,能对变量进行操作。同系统异常一样,可使用throw语句来抛出自定义异常。

自定义异常类及其使用示例 class MyException extends Exception{  public MyException(){ }  public MyException(String message){  super(message);  } } public class Ex8_6{  public static void f() throws MyException{   System.out.println("Throwing MyException");   throw new MyException("the second constructor! ");  }  public static void main(String args[]){  try{ f(); }  catch(MyException e) {   e.printStackTrace(); }  } } 运行结果: Throwing MyException MyException:the second construtor! at Ex8_6.f(Ex8_6.java:7) at Ex8_5.main(Ex8_5.java:12) 程序分析:该例题通过继承异常类Exception创建了自己的异常类MyException,并增加了两个构造方法,第一个没有明确指明调用父类构造方法,但是编译器会自动调用父类默认构造方法,第二个通过使用super关键字,调用了参数为String类型的父类构造方法。PrintStackTrace()方法将打印出“the second constructor!”信息和异常发生地点的方法调用的顺序。

多catch语句使用示例 public class Ex8_6 { public static void test(int i) { try {     int x = i;      if (x>0)        throw new ArithmeticException ("this is a Arithmetic Exception!");     else if (x<0)       throw new NullPointerException ("this is a NullPointer Exception!");      else       throw new Exception("this is a Exception!"); } catch(ArithmeticException e){ System.out.println(e.toString()); }

多catch语句使用示例(续) catch(NullPointerException e) { System.out.println(e.toString()); } catch(Exception e) { } public static void main(String[] args) {     test(-1); test(0); test(1);   } } 运行结果: java.lang.NullPointerException: this is a NullPointer Exception! java.lang.Exception: this is a Exception! java.lang.ArithmeticException: this is a Arithmetic Exception! 程序分析:在一个try区中存在的异常可能有多种类型,这时需要用多个catch块来捕获和处理这些异常。程序的main()方法中,给出了三个测试值,分别会有三个异常产生,每个异常发生时,,Java将依次逐个检查这些catch语句,发现与抛出的异常类型匹配时就执行那一段处理代码,而其余的不会被执行。

多catch语句使用注意事项 为了防止可能遗漏某一类异常catch语句,可以在后面放置一个捕获Exception类的catch语句。Exception是可以从任何类方法中“抛”出的基本类型。,因为它能够截获任何异常,从而使后面具体的异常catch语句不起作用,所以需放在最后一个位置。如果将捕获Exception的catch放在前面,编译就通不过。

本章小结 异常处理是成功设计一个Java程序的保证。本章介绍了Java语言中异常和异常类的概念,讨论了异常处理的方法。 异常是程序运行时出现的非正常情况,可以是由于程序设计本身的错误,也有可能是由于运行中出现了不可解决的问题造成了异常。异常往往会导致程序运行失败或者程序运行的终止。 在Java语言中提供了一系列的异常处理方法,程序中出现的异常都是以某个异常类的实例(对象)形式存在。

本章小结 异常类都是Exception类的子类,分为两种,一种是在Java类库中已经定义好的,叫系统定义的运行异常;另一种是由用户自己根据所设计软件的具体情况定义的异常,它也是Exception类或其子类,这一类异常在错误产生时无法自动地抛出,而是要用户设计代码创建对应的对象,并手动地用throw语句抛出。当然,凡是用户定义的异常,还要在可能产生这些异常的地方用throws语句声明这些异常类。 在Java的异常处理机制中,重点是异常的捕获和处理。Java语言用try-catch-finally语句块来捕获和处理异常,当抛出多个异常时,需要多个catch块来捕获和处理。此时,应注意catch块的捕获规则,防止捕获异常的失败。

本章小结 在Java中可以通过继承Exception类创建自定义异常类,一旦创建了自定义异常类,则该异常类的使用方法等同于系统异常类。

作业 推荐书籍: 《Robust Java中文版:Java异常处理、测试与调试》