`
isiqi
  • 浏览: 16467308 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

Java中异常机制的深入研究

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

<ccid_nobr></ccid_nobr>
<ccid_code><font color="#a52a2a">FILE *fp;
fp=fopen(filename,"rw");
if(fp==NULL){
    printf("cannot open file\n");
    exit(0);
}</font></ccid_code>


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

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

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

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

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

例1:

<ccid_nobr></ccid_nobr>
<ccid_code><font color="#a52a2a">/*isLegal于检查数据是否合法,当&gt;0时视为合法,返回合法值,
*否则视为不合法,抛出"异常"。*/
int isLegal(int dt) throws LowZeroException//这种定义本文中均称为方法与"异常"通
{                  //过throws建立了关联
	if(dt&gt;=0){
		return data;
	}
	else
		throw new LowZeroException();
}
/*自已写的异常类,继承自Exception*/
class LowZeroException extends Exception
{
	public LowZeroException(){
		super();
	}
}</font></ccid_code>


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

<ccid_nobr></ccid_nobr>
<ccid_code><font color="#a52a2a">int isLegal(int dt) {
	if(dt&gt;=0){
		return data;
	}
	else
		return -1;//通过一个特定值来表明出错
}</font></ccid_code>


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

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

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





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

二、"异常"的处理过程

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

例2:

<ccid_nobr></ccid_nobr>
<ccid_code><font color="#a52a2a">/*将关联有异常的方法包含在try模块中*/
int myMethod(int dt){
int data = 0;
try{
	int data = isLegal(dt);
}catch(LowZeroException e){
	System.out.println("发生数据错误!");
}
		return data;
	}</font></ccid_code>


三、"异常"的处理方法

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

例3:

<ccid_nobr></ccid_nobr>
<ccid_code><font color="#a52a2a">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; 
}</font></ccid_code>


从上例中可以看到方法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异常机制深入研究 #### 一、Java异常概述与分类 Java中的异常处理机制是其强大特性之一,它能够帮助开发者有效地管理程序运行时出现的错误情况,从而提高程序的健壮性和可维护性。Java中的异常主要分为三...

    Java 异常问题,深入研究.docx

    Java异常处理是编程中至关重要的一个环节,它用于处理运行时出现的问题,使得程序能够更加健壮和易于维护。在Java中,异常分为两大类:可查异常(Checked Exceptions)和不可查异常(Unchecked Exceptions)。可查...

    Java虚拟机的深入研究

    总之,Java虚拟机是Java平台的核心,它的深入研究对于Java开发者来说极其重要,可以帮助他们更好地理解代码的运行机制,提升程序性能,以及解决运行时可能出现的问题。通过阅读如《Java虚拟机规范》这样的专业书籍,...

    java编程深入研究

    《Java编程深入研究》涵盖了Java开发的多个重要方面,旨在帮助开发者从基础到高级,全面理解和掌握这门广泛使用的编程语言。在这个过程中,我们将探讨Java的环境配置、服务器的运用,以及一系列实用示例。 首先,...

    基于JAVA常见异常处理剖析.pdf

    本文深入研究了Java的异常处理机制,并结合实践,用实例说明了Java常见异常处理如何具体应用。 Java是一种面向对象的程序设计语言,其异常处理非常出色。为了提高软件的开发效率,降低开发成本,应充分发挥程序设计...

    Java编程中异常处理的方法和技巧研究.pdf

    1. Java异常处理机制 2. 异常类 3. 抛出异常 4. 捕捉异常 5. 异常处理技巧和方法 通过本文的研究和讨论,我们希望能够帮助Java开发人员更好地理解和掌握Java中的异常处理机制和技术,提高程序的质量和可靠性。

    JAVA编程中异常处理的方法和技巧研究.pdf

    【JAVA编程中异常处理的方法和技巧研究】 ...通过对Java异常处理机制的深入理解和实践,开发者可以编写出更健壮、更易于维护的代码,有效应对各种运行时可能出现的问题,从而提升软件系统的整体质量和用户体验。

    java 异常类处理

    本文将深入探讨Java中的异常类处理,包括异常的分类、处理机制以及如何有效地利用源码和工具进行调试。 首先,Java中的异常分为检查型异常(Checked Exceptions)和运行时异常(Runtime Exceptions)。检查型异常是...

    深入Java核心Java中多态的实现机制.pdf

    在深入理解和运用Java中的多态机制时,我们需要仔细研究类的继承结构,理解如何通过接口实现多态,掌握方法重写在实现多态中的作用,以及了解类型擦除和泛型编程在Java中的应用。通过实践和对文档内容的深入挖掘,...

    后端研究-保证Java精确异常的指令调度技术.pdf

    【Java精确异常】Java语言的异常处理机制是其鲁棒性的重要体现,...同时,针对Java异常处理的优化研究,如智能的指令调度策略,将在提高Java程序运行效率方面发挥关键作用,推动Java在更多领域实现更广泛和深入的应用。

    深入JAVA虚拟机第二版(java深入研究)

    这本书是Java深入研究的重要参考资料,涵盖了从基础到高级的JVM主题,对于提升Java编程技能和优化代码性能具有极大的价值。 首先,本书将详细介绍JVM的架构,包括类加载机制、内存模型以及执行引擎等核心部分。JVM...

    Java卡Java卡虚拟机解释器Java栈异常处理[定义].pdf

    【Java卡】 Java卡是一种基于Java技术的智能卡,其特点是平台无关性,这意味着Java卡可以在各种不同的硬件平台上运行,无需重新...通过深入研究和实践,可以创建一个符合Java卡规范的虚拟机,满足智能卡应用的需求。

    异常处理机制

    在深入研究源码时,理解异常处理机制的实现细节也非常重要。这可能涉及查看编译器如何生成异常处理表,以及运行时系统如何调度异常处理。虽然这些底层机制通常对普通开发者来说是透明的,但在某些情况下,了解它们的...

    Java语言程序设计异常处理方法的研究.zip

    本研究主要探讨了Java中的异常处理机制,包括异常的分类、捕获、抛出以及自定义异常等核心概念。 首先,Java中的异常是一种事件,通常表示程序执行过程中遇到的不正常情况。这些异常可以是资源问题(如文件未找到)...

    观察者模式在Java事件处理中的应用研究.pdf

    "观察者模式在Java事件处理中的应用研究" 观察者模式是一种行为型设计模式,它广泛应用于Java事件处理机制中。本文将深入分析观察者模式的组成部分和应用场景,并探讨Java事件处理机制的原理,以及事件源、事件、...

    java注解、java反射机制 jdbc 封装

    通过学习这个案例,开发者可以深入理解如何在实际项目中有效利用Java的注解和反射机制,提升代码质量和可维护性。 总之,这个案例结合了Java的三大利器——注解、反射和JDBC,旨在创建一个高效、灵活且易于扩展的...

    Java异常的深入研究与分析

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

Global site tag (gtag.js) - Google Analytics