当前位置:首页 >> 能源/化工 >>

Java第8章


第八章
异常(例外)处理与垃圾回收

课程目标
Java的异常处理机制 try-catch机制 finally处理 throw与throws抛出异常 Java的垃圾回收机制

课程定位
Java 语言 视图层 (界面/外观) 控制层 (验证/调度) SQL 语言 模式层 (处理/反馈) 持久化层 (操作/事

务) 数据存 储系统

A B C D
F Struts F HIB F SS F SSH

HTML HTML HTML HTML sHTML/JSP HTML/JSP HTML/JSP HTML/JSP JSP JSP Servlet Servlet Servlet Servlet

Servlet JSP Servlet javaBean Action Bean Action Bean

DAO/JDBC JDBC DAO/JDBC DAO/JDBC DAO/JDBC PO/hibernate

Spring/DAO Spring hibernate

什么是异常
在程序执行中,任何中断正常程序流程的异常条 件就是错误或异常。
① 表达式的计算违反了Java 语言的语义,例如整数 被0 除。 ② 在载入或链接Java 程序时出错。 ③ 超出了某些资源限制,例如使用了太多的内存。

Java 程序代码中的throw 语句被执行。 异步异常发生。异步异常的原因可能有:
① Thread 的stop 方法被调用。 ② Java 虚拟机内部错误发生。

异常处理机制
在用传统的语言编程时,程序员只能通过方法的 返回值来发出错误信息,这容易导致很多错误。 C语言程序,为了处理“异常”情况,也常利用 goto语句。 Java对“异常”的处理是面向对象的。Java的 Exception是一个描述“异常”情况的对象。 当出现“异常”情况时,一个Exception对象就产 生了,并放到产生这个“异常”的成员方法里。

异常情况分类
异常分为运行时异常和一般异常。在Java语言中,通常所 说的异常是指程序运行过程中可能出现的非正常状态,即 虚拟机的通常操作中可能遇到的异常,是一种常见的运行 错误。 在Java语言中,“异常”可以看作是一个类,异常类的根 是Throwable。 Throwable是类库java.lang包中的一个类,并派生出 Exception类和Error类两个子类。Exception类表示一种设 计或实现问题,换句话说,若程序正常运行,不会出现此 类异常。 Error类表示恢复不是不可能,但很困难的情况下的一种严 重异常,如内存溢出,程序自身不可能处理此类异常。 异常处理的5个控制关键字:
try、catch、finally、throw和throws

想象一下

异常处理程 序:警察

异常发生:交 通事故

try与catch
try语句用大括号{}指定了一段代码,该段代码可 能会抛弃一个或多个异常。 catch语句的参数类似于方法的声明,包括一个异 常类型和一个异常对象。 catch语句可以有多个,分别处理不同类的异常。 Java运行时系统从上到下分别对每个catch语句处 理的例外类型进行检测,直到找到类型相匹配的 catch语句为止。 也可以用一个catch语句处理多个异常类型,这时 它的异常类型参数应该是这多个异常类型的父类, 程序设计中要根据具体的情况来选择catch语句的 异常处理类型。

异常的作用
Java程序在运行的过程中,尽管系统能提供默认的异常处 理程序,但通常喜欢自己处理异常。因为自己处理异常:
第一:能够对错误进行修正; 第二:能够防止程序自动终止。

try模块和catch模块是配套工作的,不能单独有try模块而 没有catch模块(有时try模块可由finally模块代替);同样 也不能没有try模块而直接出现catch模块。 正常执行流程的代码放在try模块中,当程序出现异常时, 抛出一个“异常事件”的信息,同时java Runtime接受此 “异常事件”并找出相应的catch模块来处理。

Try—catch语法
try {
正常执行流程的代码; } catch(异常类型 变量) { 异常对象变量的处理; }

Try-catch 流程图示

异常类的继承结构

Object

Throwable

Error

Exception

AWTException

……

IOException

RuntimeException

一个简单的try-catch示例
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. class Arithmetic { public static void main(String arg[ ]) { int a,b,c; try { a=10; b=0; c=a/b; System.out.println("正确执行到"); } catch(ArithmeticException e) { System.out.println("分母不能为零…\n"+e.toString()); } } }

注意:程序出现异常时能从try模块转到catch模块中,一 旦出现异常将执行catch模块永远不会返回到try模块。

finally
finally 是java异常处理提供的另一个关键字,通 俗的说finally是异常处理语句结构的一部分,表示 无论什么情况都要执行的模块。 finally语句的主要作用是在try或catch转到其他部 分前做的一些“善后”工作。比如:关闭打开的 文件,释放链接、内存等系统资源。 finally语句的执行是一种无条件的操作,无论在哪 种异常下都会执行,即使try或catch模块中有 continue、return、break等关键字,或者是有 throw语句,程序都会执行finally 语句。

throw 关键字
throw总是出现在方法体中,用来抛出一个异常。 程序会在throw语句后立即终止,它后面的语句执 行不到,然后在包含它的所有try块中(可能在上 层调用方法中),从里向外寻找含有与其匹配的 catch子句的try块。 下面是一个创建并引发异常的程序,与异常匹配 的处理程序再把它引发给外层的处理程序。

示例
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. public class ThrowDemo { static void demoproc() { try { throw new NullPointerException("demo"); } catch(NullPointerException e) { System.out.println("Caught inside demoproc."); throw e; } } public static void main(String args[ ]) { try { demoproc(); } catch(NullPointerException e) { System.out.println("Recaught: " + e); } } }

throws关键字
如果一个方法可以导致一个异常但不处理它,它必须指定这种行为以 使方法的调用者可以保护它们自己而不发生异常。 要做到这点可以在方法声明中包含一个throws子句。throws总是出现 在一个方法头中,用来标明该成员方法可能抛出的各种异常。 对大多数Exception子类来说,Java 编译器会强迫你声明在一个成员 方法中抛出的异常的类型。 一个throws 子句列举了一个方法可能引发的所有异常类型。这对于除 Error或RuntimeException及它们子类以外类型的所有异常是必要的。 一个方法可以引发的所有其他类型的异常必须在throws子句中声明。 如果不这样做,将会导致编译错误。 下面是包含一个throws子句的方法声明的通用形式:
type method-name(parameter-list) throws exception-list { // body of method }

exception-list是该方法可以引发的异常列表,中间以逗号分隔。

正确处理异常
组合使用throws、try和throw 我们可以通过两种方式来恰当的处理异常:
1. 2. 使用try-catch-finally块来处理异常。 使用throws子句声明代码能引起的异常。

异常处理的思想是:尝试(try)执行一段代码,捕获 (catch)所有可能抛处的异常,最后做一些清理工作。 格式如下:
1. 2. 3. 4. 5. 6. 7. try{
//可能会引起的异常的程序段 }catch(ExceptionType e){ //处理异常的程序段 }finally{ //最后要做的清理工作 }

catch
可以有多个catch()块,每一个都指定自己的 ExceptionType,它们的顺序为:
从想捕获的特定异常到想捕获的异常的超类。 试图首先捕获超类的异常会导致编译时出错,比如,把带 有Exception类型的catch块放在带有IOException类型的 catch块前面就会导致编译时出错。

这种程序的执行结果会有以下两种情况:
1. 执行完所有try中的内容,没有跳到任何一个catch中去。 2. 执行try的过程中产生某一种异常,然后跳到其中一个 catch块中。

不管是哪一种情况,最后都会去执行finally块中的内 容,这就是finally指令的用途。

异常的类型
下面是一些经常可以见到的异常。
1. ArithmeticException:在出现不合法的数学运算时发生,比如: 除数为0。 2. ArrayIndexOutOfBoundsException:如果使用非法的索引值访问 数组,就会抛出该异常。该异常说明索引要么是负值,要么大于 或者等于该数组的大小。 3. ClassNotFoundException:说明某类被调用,但是没有找到相应 的类文件,该类名或者不正确,或者该类对程序无效。 4. FileNotFoundException:访问一个文件时,必须准备处理该异 常,这是因为创建了某File并不意味着该文件存在。 5. IOException:在读写文件时发生错误的信号,在使用流的方法 时常常会遇到该异常。 6. NullPointerException:调用使用null对象引用的方法,会见到该 异常。 7. NumberFormatException:将字符串转换为数字的时候,应该处 理该异常,以防该字符串实际上不能代表为数字。 8. StringIndexOutOfBoundsException:该异常试图在字符串边界 外进行索引。

垃圾回收
当对象被创建时,就会在Java虚拟机的堆 区中拥有一块内存 在Java虚拟机的生命周期中,Java程序会 陆续地创建无数个对象 假如所有的对象都永久占有内存,那么内 存有可能很快被消耗光,最后引发内存空 间不足的错误。

垃圾回收的优点
Java语言中,内存回收的任务由Java虚拟机来担 当,而不是由Java程序来负责。在程序的运行时 环境中,Java虚拟机提供了一个系统级的垃圾回 收器线程,它负责自动回收那些无用对象所占用 的内存,这种内存回收的过程被称为垃圾回收 (Garbage Collection)。 垃圾回收具有以下优点:
1. 把程序员从复杂的内存追踪、监测和释放等工作中解放 出来,减轻程序员进行内存管理的负担。 2. 防止系统内存被非法释放,从而使系统更加健壮和稳定。

垃圾回收的特点

1. 只有当对象不再被程序中的任何引用变量引用时, 它的内存才可能被回收。 2. 程序无法迫使垃圾回收器立即执行垃圾回收操作。 3. 当垃圾回收器将要回收无用对象的内存时,先调用 该对象的finalize()方法,该方法有可能使对象复活, 导致垃圾回收器取消回收该对象的内存。

透视Java垃圾回收
Java的堆是一个运行时数据区,类的实例(对象)从中分 配空间。 Java虚拟机(JVM)的堆中储存着正在运行的应用程序所建 立的所有对象,这些对象通过new、newarray、 anewarray和multianewarray等指令建立,但是它们不需 要程序代码来显式地释放。 在命令行中有一个参数-verbosegc 可以查看Java使用的 堆内存的情况,它的格式如下:
java -verbosegc classfile

示例
1. 2. 3. 4. 5. 6. 7. 8. 9. class TestGc { public static void main(String[ ] args) { new TestGc(); System.gc(); System.runFinalization(); } } 在这个例子中,一个新的对象TestGc被创建,由于它没有使用,所 以该对象迅速地被回收,程序编译后,执行命令:java -verbosegc TestGc 后的结果如图所示:

结果说明
机器的环境为Windows 2000 + JDK1.5.1,箭头 前后的数据178K和123K分别表示垃圾收集GC前 后所有存活对象使用的内存容量,说明有178K123K=55K的对象容量被回收,括号内的数据 1984K为堆内存的总容量,收集所需要的时间是 0.0184303秒(这个时间在每次执行的时候会有 所不同)。

finalize()方法
在撤消一个对象时,有时需要完成一些操作。例如,如果一个对象正在 持有某些非Java资源,如文件句柄或者是Windows字符字体,则要确 保在对象被销毁之前释放这些资源。 为处理这种情况,Java提供了一种称为结束的机制(finalization),使 用finalization,可以定义特殊的动作,这种动作在一个对象要被垃圾回 收器收回时执行。 要给一个类添加一个结束器,只需要定义finalize()方法。无论何时要收 回该类的对象,Java运行时就调用该方法。 在finalize()方法内要指定一个对象在被撤消前必须执行的动作。垃圾回 收器定期运行,检查不再被任何运行状态引用的对象或间接地通过其他 对象引用的对象。 在释放内存前,Java运行时调用该对象上的finalize()方法。 finalize()方法的一般形式如下:
? ? ? ? protected void finalize() { //finalization code here… }

显式的调用垃圾收集程序
1. 获取一个代表当前运行时的对象 2. 调用这个对象的gc()方法
下面是这种步骤的一个程序片断:
Runtime rt=Runtime.getRuntime(); rt.gc();

Runtime对象的四个方法
1. gc():在这个方法返回前,JVM已经执行了垃圾收 集。 2. runFinalization():在这个方法返回前,JVM已经 为所有还没有运行finalize()方法的等候垃圾收集 的对象执行了finalize()方法。 3. totalMemory():这个方法返回一个int值,它包括 JVM中为分配对象所提供的可用内存总数。 4. freeMemory():这个方法返回一个int值,这个数 值代表了剩余内存数目,该数值总是小于 totalMemory()的返回值。

本章总结
Java的异常处理机制 try-catch机制 finally处理 throw与throws抛出异常 Java的垃圾回收机制

动手实践:银行系统模拟
利用异常处理突发事件

编程实践:模拟银行存取款系统
目标 (1)编写程序实现一个银行存取款模拟系统的简单实现。 (2)自定义一个异常类,我们对Banker类中的余额进行 判断,如果欲取出的金额大于余额则手动抛出该异常。 (3)对取款的流程进行设计,每次操作完毕后都返回上 一步继续操作。 程序启动后,程序运行结果如图所示。

(1)定义一个异常类
1. 2. 3. 4. class InsillException extends Exception{ private Banker banker; private double dAmount; public InsillException(Banker banker,double dAmount){ 5. this.banker=banker; 6. this.dAmount=dAmount; 7. } 8. public String excepException(){ 9. String str="出现异常:您银行上的帐目不 足以您提取"+this.dAmount+"$"; 10. return str; 11. } 12. }

(2)定义银行类
1. public class Banker{ 2. double amount; 3. public Banker(double amount){ 4. this.amount=amount; 5. } 6. public boolean getMoney(double amount){ 7. boolean flag=false; 8. try{ 9. System.out.println("取出金额:"+amount+"$");

抛出异常
1. if(amount>this.amount){ 2. throw new InsillException(this,amount); 3. } 4. else{ 5. this.amount-=amount; 6. //System.out.println("取出金额:"+amount+"$"); 7. flag=true; 8. } 9. } 10. catch(InsillException e) 11. { 12. System.out.println(e.excepException()); 13. }finally{ 14. System.out.println("返回上一步:"); 15. } 16. return flag; 17. }

计算
1. public void putMoney(double amount){ 2. if(amount>0.0){ 3. this.amount+=amount; 4. System.out.println("存入金额:"+amount+"$"); 5. } 6. } 7. public void viewMoney(){ 8. System.out.println("查询余额:您银行上帐户上 还有:"+this.amount+"$"); 9. } 10. public void exit(){ 11. System.out.println("退出程序:按任意键退出..."); 12. }

测试
1. 2. public static void main(String args[ ]){ Banker ban=new Banker(1152.21); 3. ban.viewMoney(); 4. ban.getMoney(1000.0); 5. ban.getMoney(500.0); 6. ban.putMoney(1234.30); 7. ban.getMoney(500.0); 8. ban.exit(); 9. } 10. }


相关文章:
java第八章答案
java第八章答案_理学_高等教育_教育专区。1.进程和线程有何区别,Java 是如何实现多线程的。 答:区别:一个程序至少有一个进程,一个进程至少有一个线程;线程的划...
java第八章课后习题解答
输入/ 第 8 章 输入/输出流【1】简述 java 流的概念、特点、及表示 [解答]: Java 的流是一个比文件所包含范围更广的概念。 流是一个可被顺序访问的数据...
Java典型模块与项目实战大全(第8章)_IT168文库
Java典型模块与项目实战大全(第8章)_IT168文库_计算机软件及应用_IT/计算机_专业资料。第8章 关机工具(Timer 类+系统命令) 在 Java 语言中,线程的类除了类 Thr...
Java语言程序设计第九版第八章答案
Java语言程序设计第九版第八章答案_工学_高等教育_教育专区。Chapter 8 Objects and Classes 1. 2. See the section "Defining Classes for Objects." The ...
JAVA讲义第8章
第8 章 图形用户界面设计通过本章的学习了解 Java 语言中图形用户界面的构造与设计, 掌握其实现的基本原理和方法, 从而达到能够设计具有图形用户界面 程序的目的。...
第8章 Java中的方法之一
第8章 Java中的方法之一_计算机软件及应用_IT/计算机_专业资料。第 8 章 Java 中的方法(一)一、方法的概念 所谓方法,就是用来解决一类问题的代码的有序组合,...
第8章习题答案
第8章习题答案 java题库java题库隐藏>> 作业: 1.编写一个方法判断一个字符串在另一个字符串中出现的次数。 (提示:方法头: int getCount(String substr,String...
java程序设计第八章十二题
java程序设计第八章十二题_计算机软件及应用_IT/计算机_专业资料。假设两个线段相交。第一个线段的两个端点是(x1,x2)和(x2,y2),第 二个线段的两个端点是(...
Java程序设计第八章作业
Java程序设计第八章作业一、选择题 1.下列选项中不属于多线程作用的是___C___。 A)使多CPU系统更加有效 B)改善程序结构 C)提高内存存储空间 D)提高应用程序...
第8章 查找 习题参考答案
数据结构JAVA语言描述习... 90页 1下载券 查找 排序 习题及答案 3页 1下载...第​8​章​ ​查​找​ ​习​题​参​考​答​案...
更多相关标签:
java第一章 | java编程思想第三章 | java第八章课后题答案 | java第五章 | 第十一章 java编程 | 第一章 java语言基础 | java第八章课后答案 | java第七章 |