异常与错误区别 Error and Exception

 
异常与错误区别 Error and Exception

了解异常与错误的区别,并且知道当你截获一个异常时,应该怎么办。
by Josh Street

许多程序员并没有意识到一个错误和一个异常是有区别的,在出现问题时,这种区别对如何操作你的代码有很重要的含意(见工具条,“简介错误与异常”)。正如Mary Campione在The Java Tutorial(Java指南)中所写的,“一个异常是在一个程序执行过程中出现的一个事件,它中断了正常指令的运行。”根据American Heritage Dictionary的解释,一个错误是“偏离了可接受的代码行为的一个动作或一个实例。”

那么偏离(deviation)和中断(disruption)有什么不同呢?我们可以这么来解释:如果你正在一条路上驾驶,有人截住了你,这就是中断。如果车发动不了了,那就是偏离(除非是我的车,我们认为这种情况是normal的)。

这同Java有什么关系呢?有很大的关系。Java有个很有趣的错误和异常层次关系(见图1)。

的确,运用try {} catch (Exception e) {}的所有代码只能找到一半你的错误。但是你是否应该截获Throwable取决于你一旦截获了它,你准备怎么处理它。对Error的子集的快速了解可以让你知道许多类的名字,如VirtualMachineError、ThreadDeath和LinkageError。在你打算截获这些错误时,确信你要处理它们,因为它们是严重的问题,所以是错误。


				图1.
图1.
但ClassCastException不是一个错误吗?的确不是。一个ClassCastException——或一种异常——只是VM(虚拟机)通知你的一种方式,通过这种方式,VM让你知道,你(开发人员)已经犯了个错误,现在有一个机会来修改它。

另一方面,错误是VM的一个故障(虽然它可以是任何系统级的服务)。我们来引用JavaDoc对Error的定义:“Error是Throwable的一个子集,它指的是一个合理的应用程序不能截获的严重的问题。大多数都是反常的情况。”

所以,错误是很难处理的,一般的开发人员(当然不是你)是不能理解处理这些错误的微妙之处的。那么在你的工作中,当你觉得会产生一个足以被称为错误的一个事件时,该怎么办呢?

首先,记住错误是像异常一样被抛出的,只有一点不同。抛出一个错误的方法不需要声明它在做什么(换句话说,异常是unchecked):

public void myFirstMethod() throws Exception
    //Since it's an exception, I have to declare 
    //it in the throws clause {
    throw new Exception();
}

public void mySecondMethod()
    //Because errors aren't supposed to occur, you 
    //don't have to declare them. 
{
    throw new Error();
}

注意有几个异常是unchecked的,因此,其行为就同错误一样:NullPointerException、ClassCastException和IndexOutOfBoundsException都是RuntimeException的子类,RuntimeException及其所有的子集通常都是unchecked的。

那么你应该怎么处理这些讨厌的unchecked的异常呢?你可以在它们可能出现的方法中截获异常,但这种方法有很大的偶然性。这么做可以解决一个问题,但是它会使其它unchecked的异常中断代码的其它部分。我们应该感谢ThreadGroup类提供的一个很好的办法:

public class ApplicationLoader extends ThreadGroup
{
     private ApplicationLoader()
     {
          super("ApplicationLoader");
     }
     public static void main(String[] args)
     {
          Runnable appStarter = new Runnable()
          {
               public void run()
               {
                    //invoke your application
                    (i.e. MySystem.main(args)}
          }
          new Thread(new ApplicationLoader(), 
appStarter).start();
     }

     //We overload this method from our parent
     //ThreadGroup , which will make sure that it
     //gets called when it needs to be.  This is 
     //where the magic occurs.
public void uncaughtException(Thread thread, Throwable exception)
     {
          //Handle the error/exception.
          //Typical operations might be displaying a
          //useful dialog, writing to an event log, etc.
     }

这个方法给我们的编程带来了很大的改变。想想吧,过去当你在你的GUI中执行一个操作时,如果出现了一个unchecked的异常,你的GUI通常处于一种不正常的状态(对话框仍然打开、按钮不能激活,指针处于错误状态),但是运用这种方法,你就可以使GUI回复到其正常状态,通知用户所出现的错误,对此你会感觉良好,因为你编写了一个高质量的应用程序。

但这种技巧不仅仅用于GUI。运用过多资源的服务器应用程序可以用这种方法在全局释放资源,通常避免VM进入一种不稳定的状态。尽早并尽可能多地截获错误、以明智的方法来处理它们,这是一个伟大的程序员和一个普通的程序员之间的不同。由于你已经阅读了本文,你想成为哪种程序员就是显而易见的了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值