java异常信息丢失问题
在讲述java异常丢失问题之前,先简略的介绍一下java异常处理机制。在这里,为了防止谬解它我不得不引用理论来先说明一下什么java异常处理机制,之后再提及自身对该机制的理解。
异常情形(exceptional condition):阻止当前方法或作用域继续执行的问题。而异常处理机制就是提供一种当异常情形发生时有效解决这种异常问题的方法。貌似一句很简单的话,若要很好的应用它着实很难。而我对异常处理的理解如下,异常处理犹如一个项目计划书中的意外草案一样,在整个项目执行过程中不一定会出现问题,如果出现问题则通过意外草案来解决这个问题,以至于整个项目的进度不会僵死在那。
异常处理机制的整体结构由以下几个关键字组成:try……catch……finally (throw 、throws)
异常处理机制的实现过程:
通过try{} 来监控作用域内的所有运行时程序,当发生异常时整个程序运行状态控制权将交付给异常处理机制;然后通过catch去捕获异常并处理异常,而这里面的finally则是作为最后执行的内容(无论是否发生异常都将会执行的代码)被执行。
而今天所要说的是异常丢失的问题则是发生在异常处理过程中,也就是上面提到的catch子句中。因为catch(**Exception e)只负责捕获当前已发生的异常,至于是打印异常信息还是抛出异常那就是catch子句里面的事了,这则是恰恰产生异常丢失的根源所在。有人会问为什么我们非要看到异常信息,或者为甚么异常信息非要完整才好呢,当发生exception时我们不是有异常处理程序吗,我们通过处理程序解决异常不就可以了吗?一连串的问题都剑指异常信息丢失不会带来很大的后果。然而大家产生这种疑惑的原因是因为对异常类型的不了解所致。异常分为RuntimeException和Exception两种,虽然RuntimeExcception 是继承于Exception,但是java异常处理机制认为这种RuntimeException产生时是不会强制或者说是不需要开发人员去写处理程序解决的,因为产生运行时异常说明开发人员写的代码有漏洞,所以这种问题必须中止程序的运行。这时如果异常信息丢失那么在这个工作空间(workspace)中去寻找最初的异常爆发点就如同大海捞针了。所以异常信息丢失对于开发人员测试自己的代码无疑是一大损失。
先看一下产生异常丢失问题的方式:
1、开发人员只是catch(捕获)了异常,但是在子句中没有做任何有关异常信息处理的动作
try{
//code
}catch(Exception e)
{
//no code
}
这种方式产生的异常信息丢失,是由于开发人员的马虎造成的,如果这样做那么当程序运行时出现异常,不会显示任何的异常信息给用户。这种做法是很不合理,对程序的使用者也是很不负责的,最起码也要 执行以下 e.printStackTrace();显示出异常发生地的栈跟踪信息。所以针对这种方式导致的异常信息丢失问题,没有更好的解决办法,只能通过开发成员律己的态度来约束。
2、开发人员通过catch(捕获)了异常,并且也处理的异常,但是在处理的过程中又抛出了新的异常
try{
//code
}catch(Exception e)
{
//do something to process exception
throw new Exception();
}
这时java异常处理机制将对捕获的异常信息进行清除,将异常发生地设在新抛出异常的位置(throw new Exception();位置),相当于执行了e.fillInStackTrace()方法。就我举的例子来讲,在查看异常信息时还有可能知道最初的异常发生地在哪里,但是当程序发生嵌套调用或者远程调用时,或者说try{}子句中的代码很多时,对于我们来说寻找最初的异常发生地就是件很难的事了。所以为了解决这样的问题,java异常处理机制提供了一种名为“异常链”的方式。异常链的作用是承接上一次异常信息到当前新抛出的异常中。
我们将上面的例子稍作修改就可以了
try{
//code
}catch(Exception e)
{
//do something to process exception
throw new Exception(e);//异常链
}
将当前的异常作为即将要抛出异常构造方法的一个参数传入,这样在输出异常信息时会自动去检查是否存在原始异常,如果存在则先输出原始异常信息。目前在JDK中这样可以接收原始异常的异常类只有三个Throwable 、Exception、RuntimeException。所以自定义的异常类要想能够实现异常链的功能必须在继承上述三个类的同时添加一个构造方法能够接收原始异常,并调用父类的对应够方法。
阅读(6314) | 评论(0) | 转发(1) |