由于本文旨在探讨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这样的面向对象的语言中更是如此。Java的异常处理机制旨在帮助开发者编写更健壮、更易于维护的代码。...
这篇19页的PDF文档《深入理解java异常处理机制Java开发Java经验技巧共》可能涵盖了Java异常处理的基本概念、最佳实践以及高级用法。在Java中,异常处理通过五个关键字来实现:try、catch、finally、throw和throws。 ...
Java 异常机制详解 Java 异常机制是 Java 语言中的一种错误处理机制,它可以帮助开发者捕获和处理程序运行时的错误和异常。Java 异常机制包括 Error、Exception、检查异常、运行时异常、异常处理和 throws 关键字等...
本文旨在探讨Java的\"异常机制\",分别介绍了\"异常类\"的组织形式、\"异常\"的处理过程、\"异常\"的处理方法及使用\"异常机制\"的需要注意的问题。
通过遵循上述最佳实践,开发者可以编写出更健壮、可维护的Java代码,有效地利用Java异常处理机制来提高程序的稳定性。同时,阅读并理解"Effective Java Exceptions"文档可以帮助进一步深化对Java异常处理的理解。
深入Java异常学习指南 在Java编程中,异常处理机制是一个至关重要的部分,它不仅能够帮助开发者有效管理程序运行时可能出现的错误,还能提高程序的健壮性和可维护性。本文将深入探讨Java异常处理机制的核心知识点,...
这份“Java异常学习资料”包含了丰富的资源,帮助你深入理解Java异常机制,提升代码质量。 1. **异常概述** Java异常是一种在程序执行期间发生的错误或不正常情况,它可以是编译时错误,也可以是运行时错误。Java...
### 异常捕获者 - 深入探秘Java异常的分类与处理机制 #### 第一章:初识异常家族 在Java编程语言中,异常处理是一项非常重要的功能,它帮助开发者有效地处理运行时发生的意外情况。Java中的异常分为两大类:**受检...
3. **健壮性**:Java设计时注重安全性和错误处理,例如通过强类型检查和异常处理机制。 4. **多线程**:Java内置了对多线程编程的支持,允许开发者创建同时执行的多个线程。 5. **网络编程**:Java提供了丰富的...
Java异常机制是Java语言中用于处理程序运行时发生的错误的一种机制。它为错误提供了对象化的处理方式,使得程序可以更加健壮、易于维护。异常处理的核心在于能够使程序在遇到错误时不会直接崩溃,而是可以执行一段...
下面我们将深入探讨Java异常的各个方面。 首先,异常的概念。异常是程序在执行过程中遇到的非正常情况,通常是由某种错误引发的。这些错误可能包括用户输入的数据错误、资源不足、文件不存在等。在Java中,异常是...
Java异常处理机制是Java编程中一个至关重要的概念,它提供了对程序运行时错误的优雅处理方式。在Java中,异常是程序执行过程中发生的错误,这些错误可能会中断正常的流程。异常处理通过`try-catch-finally`块来实现...
本文将对C++和Java两种语言的异常处理机制进行深入的比较和分析,探讨它们的相似之处以及不同之处,以帮助开发者更好地理解和应用这两种语言。 首先,异常处理的基本目的是捕获并处理运行时错误,这些错误通常包括...
这篇博文“Java异常框架设计”可能探讨了如何有效地利用Java的异常处理机制来构建可靠的系统。在这个讨论中,我们将深入理解Java异常的基本概念、异常分类、以及如何通过良好的框架设计提升代码的可读性和可维护性。...
这个“java高端技术课程--Java异常处理详解”将深入探讨Java中的异常处理机制,帮助开发者提升代码质量,增强软件的鲁棒性。 异常(Exception)是程序运行时发生的错误,它可以是编译时错误,也可以是运行时错误。...
尽管提供的内容与异常处理直接相关的部分较少,但基于标题、描述以及部分上下文,我们可以深入探讨Java异常处理的相关概念。 ### Java异常概述 在Java编程语言中,异常处理是一项重要的机制,用于管理程序执行期间...
Java的异常处理机制提供了一种强大的方式来处理程序运行时的错误。通过合理使用try、catch、finally、throw和throws关键字,我们可以编写出...掌握Java异常处理的最佳实践,可以帮助我们写出更加清晰和可维护的代码。
在编程实践中,异常处理机制是保证程序健壮性和稳定性的重要手段。对于Java开发者而言,深入理解并熟练运用异常...本文提供了对Java异常处理机制的全面介绍,为读者在异常处理方面的深入学习和实践提供了坚实的基础。
首先,我们来看《深入JAVA虚拟机》这本书,它涵盖了JVM的各个关键方面,包括指令集、运行时数据区、方法区、堆内存、栈帧结构、编译与优化、异常处理和安全性等。书中通过实例解析,帮助读者理解JVM如何处理Java程序...