第7章 异常处理.

Slides:



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

Java 程序分类 Java Application :是完整程序,需要独立的解 释器解释运行;以 “.java” 为后缀的文件,以 main() 方法作为程序入口,由 java 编译器编译生 成字节码,由 Java 解释器加载执行字节码。 Java Applet 没有 main() 方法作为程序入口,是嵌在.
Java 程序设计(第二版) 普通高等教育 “ 十一五 ” 国家级规划教材 辛运帷等 编著 徐小平 主讲.
第四章 类、对象和接口.
第三讲 面向对象(上).
3.2 Java的类 Java 类库的概念 语言规则——程序的书写规范 Java语言 类库——已有的有特定功能的Java程序模块
JAVA 编 程 技 术 主编 贾振华 2010年1月.
项目6 通用堆栈.
Java程序设计教程 第一讲 Java概述.
Java的程式架構與基本觀念 Java語言的歷史 Java程式的開發環境 Java程式的架構 輸出與輸入物件之使用 工具使用方法介紹
四資二甲 第三週作業 物件導向程式設計.
面向对象的程序设计(一).
第五章 字符串.
程設一.
第二章 JAVA语言基础.
Ch07 介面與多重繼承 物件導向程式設計(II).
第5章 进一步讨论对象和类.
第三章 控制结构.
程設一.
程式設計實作.
第5章 异常处理 王德俊 上海交通大学继续教育学院.
2.1 基本資料型別 2.2 變數 2.3 運算式與運算子 2.4 輸出與輸入資料 2.5 資料型別轉換 2.6 實例
例外處理(Exception Handling)
常用工具类.
Java语言程序设计 第七部分 多线程.
Java基础 JavaSE异常.
Classes Lecturer: 曾學文.
程式敘述執行順序的轉移 控制與重複、方法 Lecturer:曾學文.
JAVA 编 程 技 术 主编 贾振华 2010年1月.
西南科技大学网络教育系列课程 高级语程序设计(Java) 第五章 继承、接口与范型.
程式設計實作.
第2章回顾 标识符:不用记,动手 关键字:if, else, switch, for, while, do, break, continue, void, …… 局部变量和成员变量 ①变量作用域 ②内存布局 基本数据类型 ①4类8种 ②互相转换 流程控制语句 ①分支 if……else, switch.
第 14 章 例外處理.
职责链模式.
Java语言程序设计 第五部分 Java异常处理.
第6章 异常的捕获及处理 6.1 异常简介 6.2 异常类的继承结构 6.3 异常处理机制 6.4 异常处理 6.5 本章小结.
Java程序设计 第9章 继承和多态.
第三章 流程控制與例外處理 資訊教育研究室 製作 注意:本投影片僅供上課使用,非經同意,請勿散播或轉載。
中国矿大计算机学院杨东平 第5章 接口和包 中国矿大计算机学院杨东平
第一次课后作业 1. C/C++/Java 哪些值不是头等程序对象 2. C/C++/Java 哪些机制采用的是动态束定
例外處理與 物件序列化(Exception Handling and Serialization of Objects)
檔案讀寫與例外處理 (File IO and Exception Handling)
9.1 程式偵錯 9.2 捕捉例外 9.3 自行拋出例外 9.4 自定例外類別 9.5 多執行緒
异常及处理.
Java程序设计 第2章 基本数据类型及操作.
C/C++/Java 哪些值不是头等程序对象
* 單元:電腦與問題解決 主題:Java物件導向程式設計-類別與物件 台南縣國立善化高中 蕭嘉民 老師
简单工厂模式.
Multithread 多執行緒 以GUI為例了解物件以及Event
JAVA 编 程 技 术 主编 贾振华 2010年1月.
《JAVA程序设计》 语音答疑 辅导老师:高旻.
第二章Java基本程序设计.
第二章 Java基本语法 讲师:复凡.
第二章 Java基本语法 讲师:复凡.
Java程式初體驗大綱 大綱 在學程式之前及本書常用名詞解釋 Hello Java!程式 在Dos下編譯、執行程式
第3章 JavaScript基本语句.
第二章 Java语法基础.
第二章 Java基本语法 讲师:复凡.
龍老師我不會Debug QQ.
第二章 Java基本语法 讲师:复凡.
Java程序设计 第17章 异常和断言.
第6單元 6-1 類別的繼承 (Class Inheritance) 6-2 抽象類別 (Abstract Class)
辅导课程十二.
JAVA 程式設計與資料結構 第三章 物件的設計.
第2章 Java语言基础.
第4讲 类和对象、异常处理 ggao.
判斷(選擇性敘述) if if else else if 條件運算子.
第二章 Java基础语法 北京传智播客教育
輸出執行結果到螢幕上 如果要將執行結果的文字和數值都「輸出」到電腦螢幕時,程式要怎麼寫? class 類別名稱 {
第二章 Java基本语法 讲师:复凡.
Presentation transcript:

第7章 异常处理

异常基础 异常是指程序在运行时发生的错误。通过异常处理机制,我们可以用一种结构化的可控方式来处理运行时地错误。尽管大多数高级程序设计语言都提供了一些异常处理机制,但是Java中的异常处理机制比其它语言提供的更简洁、更灵活。在Java中,所有的异常都用类来表示。所有的异常类都是从java.lang包中的Throwable类继承而来的。

Error和Exception 1.Error Error用来表示编译和运行错误,如程序进入了死循环、内存溢出等。Error只能在编译阶段解决,运行时程序本身无法解决,只能依靠其它程序的干预,否则会一直处于非正常状态。Error处理一般由系统承担,Java本身不提供相应的Error处理机制。 2.Exception Exception用来表示由程序活动所导致的错误,如运算时除数为0、打开一个文件时发现文件不存在等。当程序运行出现Exception时,在程序中加入异常处理代码,仍可使程序继续运行直至程序结束。 异常处理机制正是针对Exception类的

Throwable的方法 Throwable中定义了多个方法。因为所有的异常类都是Throwable的子类,所以它们都继承了Throwable的这些方法。 Throwable fillInStackTrace():返回一个包含调用栈信息的Throwable对象,该对象可以被重新抛出。 void printStackTrace():将调用栈信息输出到标准错误 。 String geiMessage():返回对异常的描述。 String getLocalizedMessage():返回对异常的本地描述。 String toString():返回一个包含异常描述的String对象。

异常的产生 Java中的异常处理机制看似十分的繁琐,实际使用时却并不复杂。下面介绍一个简单的基本异常: class Throw1{ public static void main(String args[]) { int a[]=new int[4]; System.out.println("Before exception!"); a[8]=12; //产生一个数组下标越界异常 System.out.println("After exception!"); }

我们可以看到,异常产生之后程序终止了执行,并且输出了相应的异常信息。此例中产生的异常有Java虚拟机自动抛出。 输出结果: Followed by exception! Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 8 at Throw1.main(Throw1.java:5) 上例中产生了一个数组下标越界异常,它是RuntimeException的一个子类,它是Java中的一个基本异常,要想对各种异常类有个全面的了解,需要去查看Java的JDK Documentation。 我们可以看到,异常产生之后程序终止了执行,并且输出了相应的异常信息。此例中产生的异常有Java虚拟机自动抛出。

捕获和处理异常 程序发生异常时,会生成一个异常对象,这个异常对象会在方法内部被抛出,它假设异常将被异常处理程序捕获。如果程序不捕获异常,它就要被JVM捕获,这个方法将在抛出异常的过程中结束。要是不希望方法就此结束,可以在方法内部设置一个特殊的块来监视可能产生异常的代码,然后让程序来捕获并处理异常对象从而不会影响其他语句的执行。在Java中,提供了try和catch语句来捕获和处理一个或多个异常。语法格式如下: try { // 可能产生异常的代码 } catch(Type1 e) { // 对异常类型Type1的异常处理代码 …….

其中,try块是一段可能产生异常的代码,也被叫做“监控区域”;catch语句的参数类似于方法的声明,包括一个异常类型和一个异常对象。异常类型必须为Throwable类的子类,它指明了catch语句所处理的异常类型,异常对象则在try块中产生;大括号中是异常处理程序,其中可以调用对象的方法。与一个try相关的catch语句可以有一个或多个,异常的类型决定了要执行哪个catch语句。也就是说,如果由一个catch语句指定的异常类型与发生的异常类型相符,那么就会执行这个catch语句,其他的catch语句则被跳过。

例如: class Try1{ public static void main(String args[]){ int a[]=new int[4]; try{ System.out.println("Before exception!"); a[8]=12; System.out.println("After exception"); } catch(ArrayIndexOutOfBoundsException e){ System.out.println("ArrayIndexOutOfBoundsException caught!"); catch(ArithmeticException e){ System.out.println("ArithmeticException caught!"); System.out.println("End up!");

输出结果: Before exception! ArrayIndexOutOfBoundsException caught! End up! 运行结果中可以看出,上例try块中产生了一个数组下标越界异常,这个异常对象被第一个catch语句捕获并处理,第二个catch语句则被直接跳过,紧接着执行了catch语句后面的输出语句。

如果try块中没有抛出异常,那么try块就会全部执行结束,并且会跳过它的所有catch语句,从最后一个catch后面的第一个语句继续执行。例如: class Try2{ public static void main(String args[]){ int a[]=new int[4]; try{ a[0]=12; System.out.println("No!"); } catch(ArrayIndexOutOfBoundsException e){ System.out.println("ArrayIndexOutOfBoundsException caught!"); System.out.println("End up!");

try代码块中可能会抛出一个或多个异常。我们要针对每个可能发生的异常,准备相应的异常处理程序。例如: 输出结果: Will exception be generated? No! End up! try代码块中可能会抛出一个或多个异常。我们要针对每个可能发生的异常,准备相应的异常处理程序。例如:

class Try3{ public static void main(String args[]){ int a[]={6,7,16,25,43,48,55,76}; int b[]={3,0,4,5,0,8}; for(int i=0;i<a.length;i++){ try{ System.out.println(a[i]+"/"+b[i]+"is"+a[i]/b[i]); } catch(ArithmeticException e){ System.out.println("Can't divide by zero!"); catch(ArrayIndexOutOfBoundsException e){ System.out.println("No matching element found!");

输出结果: 6/3 is 2 Can't divide by zero! 16/4 is 4 25/5 is 5 48/8 is 6 No matching element found!

捕获所有异常 当抛出异常的时候,Java会从上向下分别对每个catch语句处理的异常类型进行检测,然后按照代码的书写顺序找出“最近”的处理程序。找到匹配的处理程序之后,它便认为异常将得到处理,然后就不在继续查找。查找的时候并不要求抛出的异常同处理程序所声名的异常完全匹配。派生类的对象也可以匹配其基类的处理程序。例如:

class Try4{ public static void main(String args[]){ int a[]={6,7,16,25,43,48,55,76}; int b[]={3,0,4,5,0,8}; for(int i=0;i<a.length;i++){ try{ System.out.println(a[i]+"/"+b[i]+"is"+a[i]/b[i]); } catch(ArrayIndexOutOfBoundsException e){ System.out.println("No natching element found!"); catch(RuntimeException e){ System.out.println("Some exception generated!");

输出结果: 6/3 is 2 Some exception generated! 16/4 is 4 25/5 is 5 48/8 is 6 No natching element found! 从运行结果中我们可以看到,数组下标越界异常被第一个catch语句捕获并处理,而算术异常却被RuntimeException类型的catch语句所捕获,这是因为ArithmeticException是RuntimeException的子类。因此,如果你既想捕获超类异常,又想捕获子类异常,那么就应该把子类的catch语句放在catch语句序列的前面。

很显然,我们也可以用一个catch语句处理多个异常类型,这时它的异常类型参数应该是这些异常类型的超类。在实际情况下,我们通常不能完全确定抛出异常的类型,为了保证程序的顺利运行,我们需要捕获所有可能类型的异常。通过捕获异常类型的基类Exception就可以做到这一点: catch (Exception e) { //………………… }

抛出异常 我们可以通过throw语句手动抛出异常。其基本语法格式如下: throw Obj; 其中throw是关键字,Obj是创建的异常类型的对象。在throw语句中同样是使用new创建异常类型的对象。例如: class Throw2{ public static void main(String args[]){ try{ System.out.println("Before throw!"); throw new ArithmeticException(); } catch(ArithmeticException e){ System.out.println("ArithmeticException caught!"); System.out.println("End up!");

输出结果: Before throw! ArithmeticException caught! End up!

重新抛出异常 由catch语句捕获的异常可以重新抛出以使外部catch语句可以捕获它。重新抛出的主要原因是为了允许多个异常处理程序访问异常。重抛异常会把异常抛给上一级环境中的异常处理程序,高一级环境中捕获此异常的处理程序可以从这个异常对象中得到所有信息。

class UseRethrow{ public static void t(){ try{ System.out.println("Bofore exception!"); throw new ArithmeticException(); } catch(ArithmeticException e){ System.out.println("ArithmeticException caught!"); throw e; class RethrowDemo{ public static void main(String args[]){ UseRethrow.t(); System.out.println("Caught again!");

ArrayIndexOutOfBoundsException在方法t()中被重新抛出,又在main()中被再次捕获。 输出结果: Before exception! ArithmeticException caught! Caught again! ArrayIndexOutOfBoundsException在方法t()中被重新抛出,又在main()中被再次捕获。

finally 对于一些代码,可能会希望无论try块中的异常是否被抛出,它们都能得到执行。为了在退出try/catch代码块时指定一个要执行的代码块,可以在异常处理程序后面加上finally子句。包含finally的try/catch的基本形式如下所示: try { // 可能产生异常的代码 } catch(Type1 e){ // 对异常类型Type1的异常处理代码 ……… Finally{ // 退出try/catch代码块后要执行的代码

class Usefinally2{ public static void t(){ int a[]=new int[4]; try{ System.out.println("Before exception!"); a[8]=10; } catch(ArrayIndexOutOfBoundsException e){ System.out.println("ArrayIndexOutOfBoundsException caught!"); throw e; finally{ System.out.println("In finally clause!"); class FinallyDemo2{ public static void main(String args[]){ Usefinally2.t(); System.out.println("Caught again!");

可见无论是出于何种原因,只要离开try/catch代码块,就会执行finally代码块。 输出结果: Before exception! ArrayIndexOutOfBoundsException caught! In finally clause! Caught again! 上例中内层try块抛出了异常,finally块中的语句得到了执行。再将程序修改一下。将程序中的这一行“a[8]=10;”改为“a[1]=10;”,此时没有异常抛出,运行结果如下: 可见无论是出于何种原因,只要离开try/catch代码块,就会执行finally代码块。

异常说明 在某些情况下,如果一个方法产生自己不处理的异常,它就必须在throws子句中声名该异常,这就是异常说明,它属于方法声名的一部分,紧跟在形式参数列表之后。包含throws子句的方法的基本形式如下: returnType methodname(/*argument list*/) throwsexceptionList{ //method body } 此处,exceptionList是一个方法可能会抛出的异常的列表,各个异常之间用逗号隔开。 凡是RuntimeException及其子类的异常都不必在列表中指定。它们被称为“未被检查的异常”。其它类型异常的处理都是由编译器强制实施的。这种异常被称为“被检查的异常”。

输出结果: class ThrowsDemo{ public static void t() throws Exception{ System.out.println("Before throw!"); throw new Exception(); } public static void main(String args[]){ try{ t(); catch(Exception e){ System.out.println("Exception caught!"); 输出结果: Before throw! Exception caught!

创建自定义异常 尽管Java的内置异常处理了大多数常见的错误,但是Java的异常处理机制并不局限于处理这些错误,我们可以自己定义异常类来表示程序中可能会遇到的特定问题。创建一个异常类很容易,只需定义一个Exception的子类即可。建立新的异常类型最简单的方法就是让编译器为你产生缺省构造器,所以这几乎不用写多少代码,还可以进一步自定义异常,比如可以为异常类定义一个接受字符串参数的构造器。例如:

输出结果: Before throw! class MyException1 extends Exception{} public class DefException1{ public static void t() throws MyException1{ System.out.println("Before throw!"); throw new MyException1(); } public static void main(String args[]){ try{ t(); catch(MyException1 e){ System.out.println("MyException1 caught!"); 输出结果: Before throw! MyException1 caught!