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

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

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

    thinking

    one platform thousands thinking

    如何避免在Java中使用Checked Exception

    如何避免在Java中使用Checked Exception


    發布時間:2007.08.20 08:52     來源:賽迪網    作者:dxaw

    這 篇文章指出了Java中checked Exception的一些缺點,提出應該在程序設計中避免使用checked Exception,對于需要處理checked Exception的代碼,可以使用ExceptionAdapter這個類對checked Exception進行包裝。這篇文章的概念和ExceptionAdapter這個類均源自Bruce Eckel的Does Java need Checked Exception。

    Java的Exception分為兩類,一類是RuntimeException及 其子類,另外一類就是checked Exception。Java要求函數對沒有被catch處理掉的checked Exception,需要將其寫在函數的聲明部分。然而,這一要求常常給程序員帶來一些不必要的負擔。

    為了避免在函數聲明中寫throws部分,在Java項目里面常??梢钥吹揭韵麓a用來‘吞掉’Exception:

    try {



    // ...



    } catch (Exception ex) {



    ex.printStackTrace();



    }

    這顯然不是一個好的處理Exception辦法,事實上,catch并處理一個Exception意味著讓程序從發生的錯誤(Exception)中恢復過來。從這種意義上說,已上的代碼只可能在一些很簡單的情況下工作而不帶來問題。

    對于很多Exception,往往沒有去處理它并讓程序從錯誤中恢復出來的辦法,這 時唯一能做的事情可能就是在界面上顯示一些提示信息給用戶。這種情況下讓程序拋出遇到的Exception是更為合理的做法。然而,這樣做會使得一些函數 的聲明急劇膨脹。一個函數可能需要聲明會拋出的7、8個checked Exception,而且每個調用它的函數也需要同樣的聲明。

    比這更糟糕的是,這有可能破壞類設計的open-close原則。簡單來 說,open-close原則是指當擴展一個模塊的時候,可以不影響其現有的client。open-close原則是通過繼承來實現的,當繼承一個類的 時候,我們既擴展了這個類,也不會影響原有的client(因為對這個類沒有改動)。

    現在考慮下面這種情況,有一個父類Base:

    public class Base {

    public void foo() throws ExceptionA {

    // ...

    }

    }

    現在需要繼承Base這個類并重載foo這個方法,在新的實現中,foo可能拋出ExceptionB:

    public class Extend extends Base {

    public void foo() throws ExceptionB {

    // ...

    }

    }

    然而,這樣寫在Java里面是不合法的,因為Java把可能會拋出的Exception看作函數特征的一部分,子類聲明拋出的Exception必須是父類的子集。

    可以在Base類的foo方法中加入拋出ExceptionB的聲明,然而,這樣就破壞了open-close原則。而且,有時我們沒有辦法去修改父類,比如當重載一個Jdk里的類的時候。

    另一個可能的做法是在Extend的foo方法中catch住ExceptionB,然后構造一個ExceptionA并拋出。這是個可行的辦法但也只是一個權宜之計。

    如果使用RuntimeException,這些問題都不會存在。這說明 checked Exception并不是一個很實用的概念,也意味著在程序設計的時候,我們應該讓自己的Exception類繼承RuntimeException而不 是Exception。(這和JDK的建議正好相反,但實踐證明這樣做代碼的質量更好。)

    對于那些需要處理checked Exception的代碼,可以利用一個ExceptionAdapter的類把checked Exception包裝成一個RuntimeException拋出。ExceptionAdapter來自Bruce Eckel的Does Java need Checked Exception這篇文章,在這里的ExceptionAdapter是我根據JDK 1.4修改過的:

    public class ExceptionAdapter extends RuntimeException {



    public ExceptionAdapter(Exception ex) {



    super(ex);

    }



    public void printStackTrace(java.io.PrintStream s) {



    getCause().printStackTrace(s);

    }



    public void printStackTrace(java.io.PrintWriter s) {



    getCause().printStackTrace(s);



    }



    // rethrow()的作用是把被包裝的Exception再次拋出。



    public void rethrow()

    throws Exception

    {

    throw (Exception) getCause();

    }



    }

    (責任編輯:編輯龔勛)

    posted on 2009-02-17 11:18 lau 閱讀(297) 評論(1)  編輯  收藏 所屬分類: J2SE

    Feedback

    # re: 如何避免在Java中使用Checked Exception 2010-11-15 18:43 lau

    Java里有個很重要的特色是Exception ,也就是說允許程序產生例外狀況。而在學Java 的時候,我們也只知道Exception 的寫法,卻未必真能了解不同種類的Exception 的區別。

      首先,您應該知道的是Java 提供了兩種Exception 的模式,一種是執行的時候所產生的Exception (Runtime Exception),另外一種則是受控制的Exception (Checked Exception)。

      所有的Checked Exception 均從java.lang.Exception 繼承而來,而Runtime Exception 則繼承java.lang.RuntimeException 或java.lang.Error (實際上java.lang.RuntimeException 的上一層也是java.lang.Exception)。

      當我們撰寫程序的時候,我們很可能會對選擇某種形式的Exception 感到困擾,到底我應該選擇Runtime Exception 還是Checked Exception ?

      其實,在運作上,我們可以通過Class 的Method 如何產生某個Exception以及某個程序如何處理這個被產生來的Exception 來了解它們之間的差異。
    首先我們先建立一個Exception

    public class CException extends Exception
    {
    public CException() {}
    public CException(String message)
    {
    super(message);
    }
    }

    然后我們撰寫一個可能產生 CException 的 Class

    public class testException
    {
    public void method1() throws CException
    {
    throw new CException("Test Exception");
    }

    public void method2(String msg)
    {
    if(msg == null)
    {
    throw new NullPointerException("Message is null");
    }
    }

    public void method3() throws CException
    {
    method1();
    }

    // 以下省略
    // ...
    }

      在這三個method 中,我們看到了method1 和method2 的程序碼內都會產生Exception,但method3 的程序碼中(大括號內),并沒產生Exception,但在method3 的定義中,暗示了這個method 可能產生CException。

    呼叫method1() 的程序,必須將method1() 包含在try 與catch 中,如:

    public class runtest
    {
    // ....
    public static void main(String argv[])
    {
    testException te = new testException();
    try
    {
    te.method1();
    }
    catch(CException ce)
    {
    // ....
    }
    }
    // ...
    }

      雖然包含在try 與catch 中,并不表示這段程序碼一定會收到CException,但它的用意在于提醒呼叫者,執行這個method 可能產生的意外,而使用者也必須要能針對這個意外做出相對應的處理方式。

      當使用者呼叫method2() 時,并不需要使用try 和catch 將程序碼包起來,因為method2 的定義中,并沒有throws 任何的Exception ,如:

    public class runtest
    {
    // ....
    public static void main(String argv[])
    {

    testException te = new testException();

    // 不會產生 Exception
    te.method2("Hello");

    // 會產生 Exception
    te.method2(null);
    }
    // ...
    }

      程序在執行的時候,也不見得會真的產生NullPointerException ,這種Exception 叫做runtime exception 也有人稱為unchecked exception ,產生Runtime Exception 的method (在這個范例中是method2) 并不需要在宣告method 的時候定義它將會產生哪一種Exception 。

    在testException 的method3() 中,我們看到了另外一種狀況,也就是method3里呼叫了method1() ,但卻沒有將method1 包在try 和catch 之間。相反,在method3() 的定義中,它定義了CException,實際上就是如果method3 收到了CException ,它將不處理這個CException ,而將它往外丟。當然,由于method3 的定義中有throws CException ,因此呼叫method3 的程序碼也需要有try catch 才行。

      因此從程序的運作機制上看,Runtime Exception與Checked Exception 不一樣,然而從邏輯上看,Runtime Exception 與Checked Exception 在使用的目的上也不一樣。

      一般而言,Checked Exception 表示這個Exception 必須要被處理,也就是說程序設計者應該已經知道可能會收到某個Exception(因為要try catch住) ,所以程序設計者應該能針對這些不同的Checked Exception 做出不同的處理。

      而Runtime Exception 通常會暗示著程序上的錯誤,這種錯誤會導致程序設計者無法處理,而造成程序無法繼續執行下去。

    看看下面的例子:

    String message[] = {"message1", "message2","message3"};
    System.out.println(message[3]);

      這段程序碼在Compile 時并沒問題,但在執行時則會出現ArrayIndexOutOfBoundException 的例外,在這種狀況下,我們亦無法針對這個Runtime Exception 做出有意義的動作,這就像是我們呼叫了testException 中的method2 ,卻引發了它的NullPointerException 一樣,在這種狀況下,我們必須對程序碼進行修改,從而避免這個問題。

      因此,實際上我們應該也必須要去抓取所有的Checked Exception,同時最好能在這些Checked Exception 發生的時候做出相對應的處理,好讓程序能面對不同的狀況。

    然而對于Runtime Exception ,有些人建議將它catch 住,然后導向其它地方,讓程序繼續執行下去,這種作法并非不好,但它會讓我們在某些測試工具下認為我們的程序碼沒有問題,因為我們將Runtime Exception "處理"掉了,事實卻不然!譬如很多人的習慣是在程序的進入點后用個大大的try catch 包起來,如:

    public class runtest1
    {
    public static void main(String argv[])
    {
    try
    {
    //...
    }
    catch(Exception e)
    {
    }
    }
    }

      在這種情況下,我們很可能會不知道發生了什么Exception 或是從哪一行發出的,因此在面對不同的Checked Exception時,我們可已分別去try catch它。而在測試階段時,如果碰到Runtime Exception ,我們可以讓它就這樣發生,接著再去修改我們的程序碼,讓它避免Runtime Exception,否則,我們就應該仔細追究每一個Exception ,直到我們可以確定它不會有Runtime Exception 為止!

      對于Checked Exception 與Runtime Exception ,我想應該有不少人會有不同的觀點,無論如何,程序先要能執行,這些Exception 才有機會產生。因此,我們可以把這些Exception 當成是Bug ,也可以當成是不同的狀況(Checked Exception),或當成是幫助我們除錯的工具(Runtime Exception),但前提是我們需要處理這些Exception ,如果不處理,那么問題或狀況就會永遠留在那里。  回復  更多評論   

    主站蜘蛛池模板: 免费国产人做人视频在线观看| 亚洲精品黄色视频在线观看免费资源| 日本视频在线观看永久免费| 黄网站色在线视频免费观看| 国产性生交xxxxx免费| 亚洲AV无码成人精品区蜜桃 | 女人体1963午夜免费视频| 亚洲国产精华液网站w| 亚洲中文无码卡通动漫野外| 99精品视频在线观看免费| 女人毛片a级大学毛片免费| 亚洲精品无码mv在线观看网站| 亚洲爆乳大丰满无码专区| 1000部夫妻午夜免费| 亚洲一区二区三区香蕉| WWW亚洲色大成网络.COM| 最近2022中文字幕免费视频| 曰韩亚洲av人人夜夜澡人人爽 | 国产免费AV片在线观看播放| 永久免费看bbb| 亚洲av永久无码精品天堂久久| 免费观看男人吊女人视频| 亚洲日本中文字幕一区二区三区| 亚洲中文精品久久久久久不卡| 麻豆成人精品国产免费| 又黄又大的激情视频在线观看免费视频社区在线 | 亚洲欧洲∨国产一区二区三区| 四虎国产精品永久免费网址| 最新精品亚洲成a人在线观看| 亚欧免费一级毛片| 亚洲免费网站观看视频| 成年女人免费视频播放77777| 亚洲午夜电影在线观看| 91免费人成网站在线观看18| 色播亚洲视频在线观看| 无码国产精品一区二区免费3p| 亚洲伊人久久大香线蕉结合| 国产卡一卡二卡三免费入口| 97se亚洲国产综合自在线| 亚洲国产精品成人网址天堂| 永久免费精品影视网站|