`
jiqimiao
  • 浏览: 59562 次
  • 性别: Icon_minigender_1
  • 来自: 常州
社区版块
存档分类
最新评论

Java中异常机制的深入研究

 
阅读更多

由于本文旨在探讨Java"异常机制"的深层原理,因此关于"异常"的使用方法都不做详细说明。首先看一段非常熟悉的用于打开一个文件的C程序段:

FILE *fp;

fp=fopen(filename,"rw");

if(fp==NULL){

printf("cannot open file/n");

exit(0);

}

在这段程序中,if条件语句中的一段用来处理没有找到指定文件,或者其它原因无法正确打开指定文件。可是如果遇到一个责任心不强的程序员,他可能认为出现找不到文件的可能性很小,或者由于思路集中在程序功能的实现上而忘记了处理这种情况。这时程序同样可以正确编译,而且一般情况下也不会出现问题。但此时这段程序可以肯定说是不够健壮的,而且一旦这段程序发生了错误也会让程序员很难发现错误出在哪里。在C语言以及其它大多数高级语言中都可以举出很多这种例子。

也就是一个函数在使用的时候,可能会出现并没有达到这个函数的使用目的的情况,哪怕在这段程序的特定使用环境下发生这种异常情况的可能性只有万分之一。常用处理的方法就是,程序员在需要使用某个函数时必须充分了解可能会有什么原因导致该函数不能正确执行,然后加入相应的条件判断语句来进行处理。后面将有一个例子说明这个问题。

而Java的"异常机制"就是在处理上述问题中给了程序员非常简单而灵活的方式。一般来说,其它高级语言主要是让函数使用者来关注该函数可能会出现的异常情况,而java则是把这件事情交给方法(和函数对应的概念,在Java中称方法)的设计者来做。这对于方法的使用者来说带来的方便是不会因为责任心不强,或者办事丢三那四,会忘了在使用方法时处理可能发生的异常情况。而麻烦就是,在使用一个可能会发生异常的方法时,绝对不能视而不见,而必须做出相应的处理。也就是说象上述C程序段中,如果忘了if程序块,这个程序甚至还能蒙过一个外行上司,但当使用Java来完成这个功能时,只要用到的方法使用了"异常"机制,如果不对可能产生"异常"的方法进行相应处理,java编译器是不会让其通过的。

一、"异常类"的组织形式

Java系统类中的方法产生的异常都被组织成"异常类"(还有Error类,不在本文讨论范围),此方法和它相关的"异常类"通过throws关键字关联在一起,并且这些类都必须是Exception类的子类。任何一个自己开发的类的方法中如果可能会产生某种异常,也可以将这种异常组织成一个"异常类",但这个"异常类"同样必须是Exception的子类,或孙子类等等。

例1:

/*isLegal于检查数据是否合法,当>0时视为合法,返回合法值,

*否则视为不合法,抛出"异常"。*/

int isLegal(int dt) throws LowZeroException//这种定义本文中均称为方法与"异常"通

{                  //过throws建立了关联

if(dt>=0){

return data;

}

else

throw new LowZeroException();

}

/*自已写的异常类,继承自Exception*/

class LowZeroException extends Exception

{

public LowZeroException(){

super();

}

}

仔细观察方法isLegal(),它体现出的最值得注意的特色是,它有两种方式的函数出口,一种是通过return语句,返回的是方法本身定义的类型的实例,另一种是通过throw,返回的是"异常类"的对象实例,Java中称之为抛出"异常"。对比一下C中如何处理同样的问题的:

int isLegal(int dt) {

if(dt>=0){

return data;

}

else

return -1;//通过一个特定值来表明出错

}

由于C只能通过return返回函数值,所以在处理异常情况时则可能通过以上方式来处理。当然这就要求isLegal()函数的使用者必须知道函数中使用返回值-1来表明出现不合法数据的情况。

对比这两种处理方法,可以知道java的"异常机制"把处理异常事件的职能和方法本身的职能通过两个不同出口分离开来。

所有这些"异常类"独立于它具体服务的方法被统一组织成一个类树。"异常机制"就好比高校的后勤社会化一样,通过后勤社会化将学校的教学职能和学校的后勤保障分离开来,并且后勤集团的组织形式也是独立于学校主体的。事实证明,这种组织方式不仅提高了服务效率,也提高了服务质量。整个Java体系中的"异常类"组织形式如图1所示:

在例1中的isLegal()方法如果在调用过程中没有能正常返回整形数,而是在"异常"产生点产生了"异常"对象,那么这个"异常"对象由谁来接收,并处理它呢?以下就来解答这个问题。

二、"异常"的处理过程

Java中由try…catch语法来处理"异常",将关联有"异常类"的方法包含在try{}程序块中,catch(){}关键字可以使用形参,用于和方法产生的"异常"对象结合。当调用某个方法时,引起异常事件发生的条件成立,便会抛出"异常",原来的程序流程将会在此方法处中断,然后try模块后紧跟的catch中的"形参"和此异常对象完成了结合,继而进入了catch模块中运行。具体过程举例说明:

例2:

/*将关联有异常的方法包含在try模块中*/

int myMethod(int dt){

int data = 0;

try{

int data = isLegal(dt);

}catch(LowZeroException e){

System.out.println("发生数据错误!");

}

return data;

}

三、"异常"的处理方法

有两种方法处理"异常":第一种如例2,将含有"异常"出口的方法直接放到try块中,然后由紧随其后的catch块捕捉。第二种是不直接监听捕捉被引用方法的"异常",而是将这个"异常"关联传递给引用方法,同时监听捕捉工作也相应向上传递。

例3:

int myMethod2(int dt)

{

int data = 0;

try{

data = myMethod(dt)

}catch(LowZeroException e){

System.out.println("发生数据错误!");

e.printStackTrace();

}

return data;

}

int myMethod(int dt) throws LowZeroException

{

int data = isLegal(dt); //此处引用isLegal()方法,但并没有捕捉它的"异常"

return data;

}

从上例中可以看到方法myMethod()与它引用的方法isLegal()产生的"异常"LowZeroException建立了关联,也就是完成了将"异常"关联的向上传递,此时的myMethod()方法体中虽然只有一个return返回语句,但它事实上同样有两种方式的函数出口,一种是由return返回的整形值,另一种则是返回方法名中的throws关键字所指的"异常类"的实例对象。相应的,监听捕捉的工作交给了上一层方法myMethod2()。同样的道理,myMethod2()也可以将"异常"通过throws的关联继续向上传递。这样的话,一旦一个"异常"被捕捉到时,这个"异常"必有一个传递路径,而如果我们在捕捉点的catch程序块中加入printStackTrace()方法,便能清楚的看到这个"异常"是怎样传递过来的。例如在例3如果有"异常"被捕捉到,e.printStackTrace()打印出来的结果将是:

LowZeroException:

at Example.isLegal

at Example myMethod

at Example.myMethod2

at Example main

从上结果中我们可以看到,从LowZeroException"异常"产生点,即包含throw new LowZeroException();子句的方法开始,然后一直追溯到产生当前线程的方法(注意:printStackTrace()并不是追溯到捕捉点结束,而是到产生当前线程的方法结束)。"异常"产生点产生的LowZeroException"异常"对象,首先被赋给了isLegal()关联的LowZeroException类的无名引用,然后继续赋给myMethod()关联的LowZeroException类的无名引用,再继续赋给myMethod2()中的catch块中的形参e,最后在这里被处理掉,这个"异常"对象随即消失。可以说,catch(){}就是"异常"对象的生命终结点。

另外还要注意一点,方法与"异常"的关联可以一直向上传递,当传递到与main方法关联后,即在main()方法的定义中使用了throws Exception,这时除了虚拟机没有其它方法能够引用main()方法,且在程序中可能看不到try…catch程序块,但并不会产生错误,因为此时虚拟机会捕捉"异常",并且会默认的调用printStackTrace()方法打印出"异常"路径。总之只要一个方法关联了"异常",可以将这个"异常"关联向上传递,但是最终必须使用catch来终止"异常",或者一直传递到main()方法交给Java虚拟机来结束"异常"对象的生命,否则是通不过编译的。

四、使用"异常机制"的需要注意的几点

1.一个方法中可能会产生多种不同的异常,你可以设置多个"异常"抛出点来解决这个问题。

2."异常"对象从产生点产生后,到被捕捉后终止生命的全过程中,实际上是一个传值过程,所以你可以根据需要,来合理的控制检测到"异常"的粒度。例如在例3中,如果你并不需要知道具体产生的是LowZeroException"异常",那么你可以使用"异常"的公共父类Exception来结合"异常"对象,即catch(Exception e){…}。同样在"异常"与方法关联的传递过程中,也可以根据需要控制关联"异常"的粒度,即throws后面跟上异常对象的父类名。

3."异常机制"中还有一种特殊情况――RuntimeException"异常类"(见图1),这个"异常类"和它的所有子类都有一个特性,就是"异常"对象一产生就被Java虚拟机直接处理掉,即在方法中出现throw 子句的地方便被虚拟机捕捉了。因此凡是抛出这种"运行时异常"的方法在被引用时,不需要有try…catch语句来处理"异常"。

分享到:
评论

相关推荐

    Java异常的深入研究与分析

     本文是异常内容的集大成者,力求全面,深入的异常知识研究与分析。本文由金丝燕网撰写,参考众多网上资源,经过内容辨别取舍,文字格式校验等步骤编辑而成,以飨读者。对于本文的内容,建议小白需要多多思考力求...

    java类文件混合加密算法的研究与分析_邹煜.caj

    是有限制的,在一些较为复杂和长数据加密过程中会存在异常的现象,因此,本 文提出了一种分块Java类文件的RSA加密算法,可有效地对较长数据进行加解 密操作,节约加解密时间,提高算法的效率,具有...

    Java开发详解.zip

    031504_【第15章:Java反射机制】_Java反射机制的深入研究笔记.pdf 031505_【第15章:Java反射机制】_动态代理笔记.pdf 031506_【第15章:Java反射机制】_工厂设计模式笔记.pdf 031601_【第16章:Annotation】_系统...

    论文研究-A comparison of exception system between C and Java.pdf

    C 与Java异常处理机制的比较,鲍鹏,高珩,本文分别深入讨论了C 与Java的异常处理机制。比较了C 与Java的异常匹配处理,异常类继承体系与异常处理代码的区别,并且讨论了异常�

    基于Java的异常处理研究 (2005年)

    为了提高软件的开发效率,降低开发成本,应充分发挥程序设计语言所提供的机制。异常处理机制是Java语言的重要特征之一,正确使用异常处理机制对设计可靠、...本文深入研究了Java的异常处理机制,并提出了一些使用方法。

    基于JAVA的搜索引擎 lucene-2.2.0

    必须深入地理解IndexWriter索引器初始化的过程,以及在构造一个IndexWriter索引器过程中涉及到的一些其他的类,应该深入研究这些相关的类的定义。这样才能有助于深化IndexWriter索引器构造的原理机制。 可见,...

    深入理解Android:卷I--详细书签版

    2.4.8 JNI中的异常处理 32 2.5 本章小结 32 第3章 深入理解init 33 3.1 概述 34 3.2 init分析 34 3.2.1 解析配置文件 38 3.2.2 解析service 42 3.2.3 init控制service 48 3.2.4 属性服务 52 3.3 本章小结 ...

    Android平台的崩溃捕获机制及实现

    5年移动互联网开发经验,曾任职于中科院、Symantec、Opera,对移动App的测试、分析有较深入的研究。Android系统碎片化造成应用程序崩溃严重,在模拟器上运行良好的程序安装到某款手机上说不定就会出现崩溃的现象。...

    Java毕业设计-基于springboot开发的体育馆管理系统设计与实现-毕业论文(附毕设源代码).rar

    同时,我们也注重系统的安全性和稳定性,采用了多种安全措施和异常处理机制,确保系统数据的完整性和系统的稳定运行。 在功能实现上,我们采用了Spring Boot框架作为后端开发的基础,利用其强大的功能和灵活的扩展...

    《Python入门经典以解决计算问题为导向的Python编程实践》.((美)William F).[PDF]@ckook.pdf

    深入研究如何为模块和程序编写测试;介绍如何使用Python编写GUI;着重介绍XML、HTML、XSL和相关技术;解释如何扩展Python;分享数值编程技术;介绍Jython的内部机理,Jython是一个用Java编写的Python版本。 Python...

    asp.net知识库

    利用委托机制处理.NET中的异常 与正则表达式相关的几个小工具 你真的了解.NET中的String吗? .NET中的方法及其调用(一) 如何判断ArrayList,Hashtable,SortedList 这类对象是否相等 帮助解决网页和JS文件中的中文...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    尽我所知,除了文中特别加以标注和致谢的地方外,论文中不包含其他人已经发表或撰写过的研究成果,也不包含为获得东南大学或其它教育机构的学位或证书而使用过的材料。与我一同工作的同志对本研究所做的任何贡献均已...

    操作系统(内存管理)

    如您所见,在这个分配程序中,内存的释放使用了一个非常简单的机制,在固定时间内完成内存释放。分配内存稍微困难一些。以下是该算法的略述: 清单 5. 主分配程序的伪代码 1. If our allocator has not been ...

Global site tag (gtag.js) - Google Analytics