<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    人在江湖

      BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
      82 Posts :: 10 Stories :: 169 Comments :: 0 Trackbacks

    這篇和前面的 總結(jié)java的interface和abstract class 一樣。跳過最基礎(chǔ)語法不聊,只說一些比較tricky的東西和一些好的practice.

     

    語法:

    Exception繼承自Throwable. Throwable還有一個兒子是Error,但是一般用不到。不過有些二百五面試官喜歡問回字有幾種寫法,所以還是要知道有Error這回事的。Exception分為checked和unchecked兩種。

     

    java的checked exception一直是個很有爭議的東西。Thinking in Java的作者Bruce, C#的設(shè)計(jì)者和Martin Fowler都對checked exception持質(zhì)疑態(tài)度。 一個典型的反對理由是:"We felt it was unrealistic to require the programmer to provide handlers in situations where no meaningful action can be taken." 這話太實(shí)惠了。寫方法給caller調(diào)用,怎么能magically知道調(diào)用這個方法的所有caller,能夠處理特定的異常呢?

     

    關(guān)于Exception有個比較基本的語法是,子類override的方法如果聲明拋出exception, 只能拋出父方法聲明的exception,或者那個exception的子類。需要注意的是,“回”字還有一種寫法,對于constructor來說沒有這個限制,子類可以拋出任意exception。父類構(gòu)造函數(shù)聲明的exception,子類也必須聲明,而且子類的構(gòu)造函數(shù)不能捕捉父類聲明的exception. 這個想想也容易理解,父類構(gòu)造出錯了,兒子居然能處理還把自己生出來了,沒老子哪來的兒子?當(dāng)然你可以抬杠說老子戴綠帽子的情況。

     

    實(shí)踐:

    1. 盡量不要在構(gòu)造函數(shù)里做復(fù)雜的操作,盡量不要讓constructor拋出exception。如果在構(gòu)造函數(shù)里拋出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不是設(shè)計(jì)用來控制程序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語句試圖考慮各種情況,正好前不久有同事說了個笑話,我覺得可以輔助解釋這個問題。

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

    某日,老師在課堂上想考考學(xué)生們的智商,就問一個男孩“樹上有十只鳥,開槍打死一只,還剩幾只?”

    男孩反問“是無聲手槍,還是其他沒有聲音的槍么?”

    “不是。”

    “槍聲有多大?”

    “80~100分貝。”

    “那就是說會震的耳朵疼?”

    “是。”

    “在這個城市里打鳥犯不犯法?”

    “不犯。”

    “您確定那只鳥真的被打死啦?”

    “確定.”老師已經(jīng)不耐煩了,”拜托,你告訴我還剩幾只就行了,OK?”

    “OK.鳥里有沒有聾子?”

    “沒有。”

    “有沒有鳥智力有問題,呆傻到聽到槍響不知道飛的?”

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

    “有沒有關(guān)在籠子里的?”

    “沒有。”

    。。。

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

    后面還有一堆“例外”情況。我們寫程序總不能真寫成

    if(鳥是聾子)

    else if(鳥是傻子)

    else if(鳥是瘸子)

    原則應(yīng)該是,如果一些情況確實(shí)是 “例外情況”,就用exception處理吧。不要很勤奮地寫一堆defensive的判斷。我們不會有故事里的小男孩兒思維那么滴水不漏的。別把Java程序退回c語言了。另一個例子是FileNotFoundException, java I/O沒有讓你每次用文件都提前調(diào)用exists()檢查一下,我想原因不光是 檢查文件的那一毫秒文件存在,run到下一步的時候,下一毫秒文件消失了,Sun沒覺得你人品那么壞吧。理念仍然是,如果你覺得文件肯定存在,你就直接用吧,一旦不存在,你再另外當(dāng)成異常情況處理。不要讓一堆if…else弄臟了程序。

     

    3. exception有個典型用法是在方法體中,進(jìn)行參數(shù)合法性校驗(yàn)

     

       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語句更方便。可以根據(jù)實(shí)際情況取舍。

     

    4. 既然上面說了checked exception本身是java設(shè)計(jì)不太合理的地方。我傾向于說,應(yīng)該及時把checked exception translate成unchecked. 我知道exception的處理原則有一條是,如果你不知道怎么處理它,就不要捕捉它。 對于checked exception來說,它總force你去處理,太討厭了。如果caller不知道怎么處理,留著給更上層的程序處理…底層的程序都不會處理,一般來說上層的程序就更不知道該怎么處理了,那還不如在盡量底層的調(diào)用中,要么處理它(這種情況很少,打log之類的算不上“處理”),要么就轉(zhuǎn)成RuntimeException拋上來, 消滅掉checked exception帶來的burden. 注意:translate exception的過程中,不要扔了原來的exception, 而要把它放在exception constructor的argument里, new RuntimeException(e)。這是很基本的東西,不多說。

     

    5. 不要吞exception. 這個太基礎(chǔ),不多說。

     

    6. 見到exception要把它記log里,而不是簡單print stack一下,log4j的api有可以接受Throwable作為參數(shù)的。

     

    7. 每層拋出來的exception要對當(dāng)前這一層有意義,比如persistence層出問題,UI上你告訴客戶hibernate的session關(guān)閉了,不能繼續(xù)load數(shù)據(jù)了,客戶還以為你的程序怎么跟狗熊一樣還會冬眠的。即使是UI層以下,底層exception,比如sql exception也不要爬到domain層里處理

     

    8. apache commons的lang包里有ExceptionUtils類,玩兒exception最好把這個工具揣口袋里。

    9.exception是設(shè)計(jì)的一部分, 但它不同于API的設(shè)計(jì)。通常我們設(shè)計(jì)API的時候,不會設(shè)計(jì)一個函數(shù)destroyBaghdad(),通常我們會寫destroyCity(Baghdad)。這樣做的目的是為了重用。換句話說,你設(shè)計(jì)API的時候,總是裝作忘了use case(caller), 而去寫適合復(fù)用的API, 盡管上面的例子use case就是destroy Baghdad, 你還是要寫更general的destroyCity函數(shù),然后把城市的名字作為參數(shù)傳進(jìn)去.但exception的設(shè)計(jì)不應(yīng)該用同樣的思路做,因?yàn)槟愫茈y料想到復(fù)用的情況下,你聲明的exception是不是總能在任何情況下都得到妥善的處理。舉個例子,這是我臨時想的例子,形象但是科技太超前了。我們寫一個print()程序給打印機(jī)A,print()的時候沒有紙可以拋一個checked NoPaperException,這時候exceptino的處理程序可以自動加載紙(目前這么高級的功能正在貝爾實(shí)驗(yàn)室研發(fā)呢)。也許有新型的打印機(jī)B總是先加紙,后打印,那么永遠(yuǎn)也不存在NoPaperException。如果打印機(jī)是老式打印機(jī)C,不會自動加載紙,見到NoPaterException也無計(jì)可施,沒法處理。checked exception的哲學(xué)是,強(qiáng)制讓caller處理它。從上面的例子看,只有A打印機(jī)需要并能夠處理NoPaperException。 B打印機(jī)不需要處理exception。C打印機(jī)沒能力處理exception. 所以,|“需要并能夠”處理是個太嚴(yán)格的限制,一般情況下不應(yīng)該用checked exception. 我們可以讓print聲明拋出unchecked exception. 提醒caller可以處理它,但是對于不應(yīng)該處理它的caller也不強(qiáng)制去處理它。

    posted on 2011-02-22 00:12 人在江湖 閱讀(9426) 評論(5)  編輯  收藏 所屬分類: java

    Feedback

    # re: 總結(jié)java的exception 2011-02-22 21:43 人在江湖
    很奇怪,這篇blog點(diǎn)擊率高的離譜,你們是怎么看到這個blog的?我之前的blog每天最多一千出頭的點(diǎn)擊率,這篇24小時內(nèi)到四千多了,真的困惑。  回復(fù)  更多評論
      

    # re: 總結(jié)java的exception 2011-02-22 23:01 HappyGao
    @人在江湖
    是從首頁看到的呀。  回復(fù)  更多評論
      

    # re: 總結(jié)java的exception[未登錄] 2011-02-24 16:29 llq
    樓主很幽默,我是初學(xué)者,多多向你學(xué)習(xí)  回復(fù)  更多評論
      

    # re: 總結(jié)java的exception 2011-02-25 13:24 Lu Han
    好文!
    最近灑家剛剛被問到回字的寫法哦!  回復(fù)  更多評論
      

    # re: 總結(jié)java的exception 2011-02-28 09:10 mashiguang
    你都罵了250了,我懂不敢告訴你是“茴”而非“回”了,管他3721,我就孔乙己一回,相信樓主明白我是好意提醒。  回復(fù)  更多評論
      

    主站蜘蛛池模板: 国产精品亚洲专区无码牛牛| 亚洲AV无码一区二区乱子伦| 国产无遮挡又黄又爽免费视频| 国产精品1024永久免费视频| 久久午夜伦鲁片免费无码| 久久国产乱子伦精品免费一| 嫩草在线视频www免费看| baoyu777永久免费视频| 成人影片一区免费观看| 成人片黄网站色大片免费观看APP| a级日本高清免费看| 黄色网址在线免费| 99视频免费播放| 日本最新免费网站| 免费毛片在线看片免费丝瓜视频| 成人免费午夜视频| 国产jizzjizz视频免费看| 全部免费毛片在线| 亚洲高清无码专区视频| 亚洲愉拍99热成人精品热久久| 精品亚洲综合久久中文字幕| 久久精品国产亚洲精品2020| 亚洲人成在线精品| 亚洲精品天堂成人片AV在线播放| 国产成人亚洲综合无| 国产区在线免费观看| 免费女人高潮流视频在线观看| 青青视频观看免费99| 国产一级特黄高清免费大片| 亚洲中文字幕第一页在线| 久久精品国产亚洲av高清漫画 | 久久成人a毛片免费观看网站| 免费精品无码AV片在线观看| 成年轻人网站色免费看| 亚洲精品网站在线观看不卡无广告| 九月丁香婷婷亚洲综合色| 亚洲av无码不卡久久| 一区二区三区AV高清免费波多| 日韩视频在线观看免费| 毛片A级毛片免费播放| 精品亚洲成α人无码成α在线观看|