`
joachimz
  • 浏览: 19012 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

Exception处理的一些思考

阅读更多
Java是少数几个把exception放在语言层来处理的语言之一,也曾作为一个重要卖点来吹捧,但是我们真地在正确的使用exception吗?我们从exception机制中得到好处了吗?我看未必!

    我们现在都知道捕获而不处理的是有害处的,但是简单的e.printStackTrace()甚至System.out.println(e)或者log.error(e, "Error Occurs!")这样就算处理了吗?他对我们应用程序的健壮性或者程序处理有何好处?答案是绝对没有,他只为你在发生问题后来查找错误原因提供些帮助,用户并没有得到任何的好处!自从java1.4后引入了exception层次(cause)后,于是大家多了一种自认为更好的选择throw new UniqueBizzException(anyException);多么优雅,我的程序都是抛出我的意外!但事实真是这样吗?

    在我看来这是一个更糟糕的用法。想想看,如果你是这个方法的使用者,不管什么错误,你统统都是得到一个UniqueBizzException,你能对他做些什么呢?好像也只能再一次抛出去。

    我们还是回过头来看看为什么我们需要exception,我的观点是exception就是对错误进行类型化,对象化。就如同其他事物被类型化,对象化一样!它让错误有了更多的信息、更多内涵。从而我们在程序中可以处理它而不是把它直接抛给可怜的用户甚至干脆屏蔽掉!根据这些错误类型或者信息,从而可以改变我们的程序处理流程,对不同的错误采取不同处理方式,这才是exception的正确用途。例如发生ValidateException时候,我们应该收集发生错误的field和原因,重新回到form去显示提示用户,发生UserAccountExpiredException则要求用户重新登陆等等。当然并不一定都要使用类型,例如像SQLException那样包含errorCode来区分错误类型也可以。总之当你需要抛出Exception的时候,你的exception中应该包含可以让程序简易获取错误类型和原因的信息,从而决定处理方式,而不是一个笼统的错误让接下来的使用者无法处理。

    当然再好的程序也不可能处理全部错误,这时候怎么办呢?既然不能处理,那就不管它,让它一层层交接给可以处理他的调用者!java提供了另一种错误类型:unchecked exception(RuntimeException以及其子类)。java语言不会强行要求使用者处理或者抛出这类错误,发生的时候它会自动抛出。最经典的反模式是EJB中的RemoteException,如果你捕获了这个错误,你能做什么呢?什么也不能做,只要在最后告诉用户这是一个系统错误,它可能的原因1、程序错误2、某种原因服务暂时不能用等等。总之这个是应用程序无法处理的。既然你什么都不能做,那就应该什么也不要做,就应该是一个unchecked exception。而不应该一次次抓了又放,或者包一层再放。这样做除了让程序更罗嗦、错误藏得更深、内存占用更多,没有任何好处!也许有人会叫,可能涉及到一些资源释放的问题,所以要先抓后放。这就更加错了,资源释放要处理的话也应该放在finally块中,否则单是java中到处充斥的NPE早就把你资源耗光了。

   以上是我在看pafa3种对exception处理的时候一些自己的思考,没有去查ThinkInJava或者EffectiveJava之类书中对Exception的建议,仅供大家探讨!

    BTW:最近看到一个绝佳Idea,来自澳洲的Mike Cannon-Brookes(俺比较崇拜的实干家之一),留作记录:可以实现一个ThreadLocalLoggingAppender(Appender是log4j中的概念,pafa logging中应该有类似概念),利用Filter或者Interceptor在服务(可以是Servlet也可以是EJB)开始后启动,退出后关闭,如果发生exception就可以记录拥有全部信息,否则按设置记录信息!
public class ThreadLocalErrorLogAppender extends AppenderSkeleton {
  protected void append(LoggingEvent event); {
  ThreadLocalErrorCollection.add(System.currentTimeMillis();, event);;
  }
  public void close(); { }
  public boolean requiresLayout(); {
    return false;
  }
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics