<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


    發(fā)布時(shí)間:2007.08.20 08:52     來源:賽迪網(wǎng)    作者:dxaw

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

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

    為了避免在函數(shù)聲明中寫throws部分,在Java項(xiàng)目里面常常可以看到以下代碼用來‘吞掉’Exception:

    try {



    // ...



    } catch (Exception ex) {



    ex.printStackTrace();



    }

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

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

    比這更糟糕的是,這有可能破壞類設(shè)計(jì)的open-close原則。簡(jiǎn)單來 說,open-close原則是指當(dāng)擴(kuò)展一個(gè)模塊的時(shí)候,可以不影響其現(xiàn)有的client。open-close原則是通過繼承來實(shí)現(xiàn)的,當(dāng)繼承一個(gè)類的 時(shí)候,我們既擴(kuò)展了這個(gè)類,也不會(huì)影響原有的client(因?yàn)閷?duì)這個(gè)類沒有改動(dòng))。

    現(xiàn)在考慮下面這種情況,有一個(gè)父類Base:

    public class Base {

    public void foo() throws ExceptionA {

    // ...

    }

    }

    現(xiàn)在需要繼承Base這個(gè)類并重載foo這個(gè)方法,在新的實(shí)現(xiàn)中,foo可能拋出ExceptionB:

    public class Extend extends Base {

    public void foo() throws ExceptionB {

    // ...

    }

    }

    然而,這樣寫在Java里面是不合法的,因?yàn)镴ava把可能會(huì)拋出的Exception看作函數(shù)特征的一部分,子類聲明拋出的Exception必須是父類的子集。

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

    另一個(gè)可能的做法是在Extend的foo方法中catch住ExceptionB,然后構(gòu)造一個(gè)ExceptionA并拋出。這是個(gè)可行的辦法但也只是一個(gè)權(quán)宜之計(jì)。

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

    對(duì)于那些需要處理checked Exception的代碼,可以利用一個(gè)ExceptionAdapter的類把checked Exception包裝成一個(gè)RuntimeException拋出。ExceptionAdapter來自Bruce Eckel的Does Java need Checked Exception這篇文章,在這里的ExceptionAdapter是我根據(jù)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();

    }



    }

    (責(zé)任編輯:編輯龔勛)

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

    Feedback

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

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

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

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

      當(dāng)我們撰寫程序的時(shí)候,我們很可能會(huì)對(duì)選擇某種形式的Exception 感到困擾,到底我應(yīng)該選擇Runtime Exception 還是Checked Exception ?

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

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

    然后我們撰寫一個(gè)可能產(chǎn)生 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();
    }

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

      在這三個(gè)method 中,我們看到了method1 和method2 的程序碼內(nèi)都會(huì)產(chǎn)生Exception,但method3 的程序碼中(大括號(hào)內(nèi)),并沒產(chǎn)生Exception,但在method3 的定義中,暗示了這個(gè)method 可能產(chǎn)生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 中,并不表示這段程序碼一定會(huì)收到CException,但它的用意在于提醒呼叫者,執(zhí)行這個(gè)method 可能產(chǎn)生的意外,而使用者也必須要能針對(duì)這個(gè)意外做出相對(duì)應(yīng)的處理方式。

      當(dāng)使用者呼叫method2() 時(shí),并不需要使用try 和catch 將程序碼包起來,因?yàn)閙ethod2 的定義中,并沒有throws 任何的Exception ,如:

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

    testException te = new testException();

    // 不會(huì)產(chǎn)生 Exception
    te.method2("Hello");

    // 會(huì)產(chǎn)生 Exception
    te.method2(null);
    }
    // ...
    }

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

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

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

      一般而言,Checked Exception 表示這個(gè)Exception 必須要被處理,也就是說程序設(shè)計(jì)者應(yīng)該已經(jīng)知道可能會(huì)收到某個(gè)Exception(因?yàn)橐猼ry catch住) ,所以程序設(shè)計(jì)者應(yīng)該能針對(duì)這些不同的Checked Exception 做出不同的處理。

      而Runtime Exception 通常會(huì)暗示著程序上的錯(cuò)誤,這種錯(cuò)誤會(huì)導(dǎo)致程序設(shè)計(jì)者無法處理,而造成程序無法繼續(xù)執(zhí)行下去。

    看看下面的例子:

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

      這段程序碼在Compile 時(shí)并沒問題,但在執(zhí)行時(shí)則會(huì)出現(xiàn)ArrayIndexOutOfBoundException 的例外,在這種狀況下,我們亦無法針對(duì)這個(gè)Runtime Exception 做出有意義的動(dòng)作,這就像是我們呼叫了testException 中的method2 ,卻引發(fā)了它的NullPointerException 一樣,在這種狀況下,我們必須對(duì)程序碼進(jìn)行修改,從而避免這個(gè)問題。

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

    然而對(duì)于Runtime Exception ,有些人建議將它c(diǎn)atch 住,然后導(dǎo)向其它地方,讓程序繼續(xù)執(zhí)行下去,這種作法并非不好,但它會(huì)讓我們?cè)谀承y(cè)試工具下認(rèn)為我們的程序碼沒有問題,因?yàn)槲覀儗untime Exception "處理"掉了,事實(shí)卻不然!譬如很多人的習(xí)慣是在程序的進(jìn)入點(diǎn)后用個(gè)大大的try catch 包起來,如:

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

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

      對(duì)于Checked Exception 與Runtime Exception ,我想應(yīng)該有不少人會(huì)有不同的觀點(diǎn),無論如何,程序先要能執(zhí)行,這些Exception 才有機(jī)會(huì)產(chǎn)生。因此,我們可以把這些Exception 當(dāng)成是Bug ,也可以當(dāng)成是不同的狀況(Checked Exception),或當(dāng)成是幫助我們除錯(cuò)的工具(Runtime Exception),但前提是我們需要處理這些Exception ,如果不處理,那么問題或狀況就會(huì)永遠(yuǎn)留在那里。  回復(fù)  更多評(píng)論   

    主站蜘蛛池模板: 视频免费在线观看| 久久精品免费观看| 午夜成年女人毛片免费观看| 亚洲视频免费一区| 69式互添免费视频| 亚洲av日韩av无码av| 成年人免费网站在线观看| 亚洲日韩国产二区无码| 在线jyzzjyzz免费视频| 亚洲成av人无码亚洲成av人| 亚洲A∨午夜成人片精品网站| 日本特黄特色AAA大片免费| 国产亚洲成归v人片在线观看| 精品国产免费一区二区三区| 国产精一品亚洲二区在线播放| 91香蕉国产线观看免费全集| 亚洲乱码卡一卡二卡三| 日韩激情淫片免费看| 国产精品高清免费网站| 亚洲精品无码不卡| 91在线视频免费播放| 免费又黄又爽又猛大片午夜| 亚洲日本一区二区三区在线| 最近中文字幕大全中文字幕免费 | selaoban在线视频免费精品| 亚洲综合在线另类色区奇米| 免费观看久久精彩视频| 亚洲另类精品xxxx人妖| 国产免费av片在线无码免费看| 国产免费一级高清淫曰本片| 久久国产亚洲精品无码| 美女被免费视频网站a国产| 久久久精品国产亚洲成人满18免费网站| 久久噜噜噜久久亚洲va久| 在线免费视频一区二区| 国产一区二区免费| 亚洲av最新在线观看网址| 亚洲av无码一区二区三区乱子伦 | 在线观看免费视频网站色| 亚洲av产在线精品亚洲第一站| 四虎国产精品免费视|