总结java的exception

这篇和前面的 总结java的interface和abstract class 一样。跳过最基础语法不聊,只说一些比较tricky的东西和一些好的practice.

 

语法:

Exception继承自Throwable. Throwable还有一个儿子是Error,但是一般用不到。不过有些二百五面试官喜欢问回字有几种写法,所以还是要知道有Error这回事的。Exception分为checked和unchecked两种。

 

java的checked exception一直是个很有争议的东西。Thinking in Java的作者Bruce, C#的设计者和Martin Fowler都对checked exception持质疑态度。 一个典型的反对理由是:"We felt it was unrealistic to require the programmer to provide handlers in situations where no meaningful action can be taken." 这话太实惠了。写方法给caller调用,怎么能magically知道调用这个方法的所有caller,能够处理特定的异常呢?

 

关于Exception有个比较基本的语法是,子类override的方法如果声明抛出exception, 只能抛出父方法声明的exception,或者那个exception的子类。需要注意的是,“回”字还有一种写法,对于constructor来说没有这个限制,子类可以抛出任意exception。父类构造函数声明的exception,子类也必须声明,而且子类的构造函数不能捕捉父类声明的exception. 这个想想也容易理解,父类构造出错了,儿子居然能处理还把自己生出来了,没老子哪来的儿子?当然你可以抬杠说老子戴绿帽子的情况。

 

实践:

1. 尽量不要在构造函数里做复杂的操作,尽量不要让constructor抛出exception。如果在构造函数里抛出exception,需要用nested try block. 如下:

   1: public class Cleanup { 
   2:   public static void main(String[] args) { 
   3:     try { 
   4:       InputFile in = new InputFile("Cleanup.java"); 
   5:       try { 
   6:         String s; 
   7:         int i = 1; 
   8:         while((s = in.getLine()) != null) 
   9:           ; // Perform line-by-line processing here... 
  10:       } catch(Exception e) { 
  11:         System.out.println("Caught Exception in main"); 
  12:         e.printStackTrace(System.out); 
  13:       } finally { 
  14:         in.dispose(); 
  15:       } 
  16:     } catch(Exception e) { 
  17:       System.out.println("InputFile construction failed"); 
  18:     } 
  19:   } 
  20: } 

而不是用finally来做清理工作。

 

2. exception的一个基本使用原则是,exception不是设计用来控制程序flow的。 这是很简单的道理,还是引用effective java的一个例子吧

   1: // Horrible abuse of exceptions. Don't ever do this!
   2: try {
   3: int i = 0;
   4: while(true)
   5: range[i++].climb();
   6: } catch(ArrayIndexOutOfBoundsException e) {
   7: }

我真正要说明的是,上面说的原则很对,但是走到极端就不对了。有的人为了 不用exception控制程序flow, 就写一大堆的if…else语句试图考虑各种情况,正好前不久有同事说了个笑话,我觉得可以辅助解释这个问题。

=============================

某日,老师在课堂上想考考学生们的智商,就问一个男孩“树上有十只鸟,开枪打死一只,还剩几只?”

男孩反问“是无声手枪,还是其他没有声音的枪么?”

“不是。”

“枪声有多大?”

“80~100分贝。”

“那就是说会震的耳朵疼?”

“是。”

“在这个城市里打鸟犯不犯法?”

“不犯。”

“您确定那只鸟真的被打死啦?”

“确定.”老师已经不耐烦了,”拜托,你告诉我还剩几只就行了,OK?”

“OK.鸟里有没有聋子?”

“没有。”

“有没有鸟智力有问题,呆傻到听到枪响不知道飞的?”

“没有,智商都在200以上!”

“有没有关在笼子里的?”

“没有。”

。。。

==============================

后面还有一堆“例外”情况。我们写程序总不能真写成

if(鸟是聋子)

else if(鸟是傻子)

else if(鸟是瘸子)

原则应该是,如果一些情况确实是 “例外情况”,就用exception处理吧。不要很勤奋地写一堆defensive的判断。我们不会有故事里的小男孩儿思维那么滴水不漏的。别把Java程序退回c语言了。另一个例子是FileNotFoundException, java I/O没有让你每次用文件都提前调用exists()检查一下,我想原因不光是 检查文件的那一毫秒文件存在,run到下一步的时候,下一毫秒文件消失了,Sun没觉得你人品那么坏吧。理念仍然是,如果你觉得文件肯定存在,你就直接用吧,一旦不存在,你再另外当成异常情况处理。不要让一堆if…else弄脏了程序。

 

3. exception有个典型用法是在方法体中,进行参数合法性校验

 

   1: public BigInteger mod(BigInteger m) {
   2: if (m.signum() <= 0)
   3: throw new ArithmeticException("Modulus <= 0: " + m);
   4: ... // Do the computation
   5: }

也有很多人用assert语句判断, 比如 Assert.notNull(object)。手动抛exception可以抛特定的类型,assert语句更方便。可以根据实际情况取舍。

 

4. 既然上面说了checked exception本身是java设计不太合理的地方。我倾向于说,应该及时把checked exception translate成unchecked. 我知道exception的处理原则有一条是,如果你不知道怎么处理它,就不要捕捉它。 对于checked exception来说,它总force你去处理,太讨厌了。如果caller不知道怎么处理,留着给更上层的程序处理…底层的程序都不会处理,一般来说上层的程序就更不知道该怎么处理了,那还不如在尽量底层的调用中,要么处理它(这种情况很少,打log之类的算不上“处理”),要么就转成RuntimeException抛上来, 消灭掉checked exception带来的burden. 注意:translate exception的过程中,不要扔了原来的exception, 而要把它放在exception constructor的argument里, new RuntimeException(e)。这是很基本的东西,不多说。

 

5. 不要吞exception. 这个太基础,不多说。

 

6. 见到exception要把它记log里,而不是简单print stack一下,log4j的api有可以接受Throwable作为参数的。

 

7. 每层抛出来的exception要对当前这一层有意义,比如persistence层出问题,UI上你告诉客户hibernate的session关闭了,不能继续load数据了,客户还以为你的程序怎么跟狗熊一样还会冬眠的。即使是UI层以下,底层exception,比如sql exception也不要爬到domain层里处理

 

8. apache commons的lang包里有ExceptionUtils类,玩儿exception最好把这个工具揣口袋里。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值