在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Java/ 異常(二)
Java 集合細節(jié)(四):保持 compareTo 和 equals 同步
Iterator
使用序列化實現(xiàn)對象的拷貝
fail-fast 機制
關(guān)鍵字 final
Vector
HashTable
Java 集合細節(jié)(一):請為集合指定初始容量
強制類型轉(zhuǎn)換
數(shù)組之一:認識 JAVA 數(shù)組
Java 集合細節(jié)(三):subList 的缺陷
hashCode
ArrayList
數(shù)組之二
List 總結(jié)
LinkedList
Java 提高篇(九)—–實現(xiàn)多重繼承
Java 的四舍五入
關(guān)鍵字 static
理解 Java 的三大特性之多態(tài)
抽象類與接口
集合大家族
異常(二)
Java 集合細節(jié)(二):asList 的缺陷
Map 總結(jié)
TreeSet
equals() 方法總結(jié)
Java 提高篇(十)—–詳解匿名內(nèi)部類
HashMap
Stack
詳解內(nèi)部類
TreeMap
異常(一)
詳解 Java 定時任務(wù)
HashSet
字符串
理解 Java 的三大特性之繼承
理解 Java 的三大特性之封裝
代碼塊

異常(二)

承接上篇博文:Java提高篇—–異常(一)

五、自定義異常

Java 確實給我們提供了非常多的異常,但是異常體系是不可能預(yù)見所有的希望加以報告的錯誤,所以 Java 允許我們自定義異常來表現(xiàn)程序中可能會遇到的特定問題,總之就是一句話:我們不必拘泥于 Java 中已有的異常類型。

Java 自定義異常的使用要經(jīng)歷如下四個步驟:

1、定義一個類繼承 Throwable 或其子類。

2、添加構(gòu)造方法(當然也可以不用添加,使用默認構(gòu)造方法)。

3、在某個方法類拋出該異常。

4、捕捉該異常。


    /** 自定義異常 繼承Exception類 **/
    public class MyException extends Exception{
        public MyException(){

        }

        public MyException(String message){
            super(message);
        }
    }

    public class Test {
        public void display(int i) throws MyException{
            if(i == 0){
                throw new MyException("該值不能為0.......");
            }
            else{
                System.out.println( i / 2);
            }
        }

        public static void main(String[] args) {
            Test test = new Test();
            try {
                test.display(0);
                System.out.println ("---------------------");
            } catch (MyException e) {
                e.printStackTrace();
            }
        }
    }

運行結(jié)果:

六、異常鏈

在設(shè)計模式中有一個叫做責(zé)任鏈模式,該模式是將多個對象鏈接成一條鏈,客戶端的請求沿著這條鏈傳遞直到被接收、處理。同樣 Java 異常機制也提供了這樣一條鏈:異常鏈。

我們知道每遇到一個異常信息,我們都需要進行 try…catch,一個還好,如果出現(xiàn)多個異常呢?分類處理肯定會比較麻煩,那就一個 Exception 解決所有的異常吧。這樣確實是可以,但是這樣處理勢必會導(dǎo)致后面的維護難度增加。最好的辦法就是將這些異常信息封裝,然后捕獲我們的封裝類即可。

誠然在應(yīng)用程序中,我們有時候不僅僅只需要封裝異常,更需要傳遞。怎么傳遞?throws!!binge,正確?。〉侨绻麅H僅只用 throws 拋出異常,那么你的封裝類,怎么辦??

我們有兩種方式處理異常,一是 throws 拋出交給上級處理,二是 try…catch 做具體處理。但是這個與上面有什么關(guān)聯(lián)呢?try…catch 的 catch 塊我們可以不需要做任何處理,僅僅只用 throw 這個關(guān)鍵字將我們封裝異常信息主動拋出來。然后在通過關(guān)鍵字 throws 繼續(xù)拋出該方法異常。它的上層也可以做這樣的處理,以此類推就會產(chǎn)生一條由異常構(gòu)成的異常鏈。

通過使用異常鏈,我們可以提高代碼的可理解性、系統(tǒng)的可維護性和友好性。

同理,我們有時候在捕獲一個異常后拋出另一個異常信息,并且希望將原始的異常信息也保持起來,這個時候也需要使用異常鏈。

在異常鏈的使用中,throw 拋出的是一個新的異常信息,這樣勢必會導(dǎo)致原有的異常信息丟失,如何保持?在 Throwable 及其子類中的構(gòu)造器中都可以接受一個 cause 參數(shù),該參數(shù)保存了原有的異常信息,通過 getCause ()就可以獲取該原始異常信息。

語法:


    public void test() throws XxxException{
            try {
                //do something:可能拋出異常信息的代碼塊
            } catch (Exception e) {
                throw new XxxException(e);
            }
        }

示例:


    public class Test {
        public void f() throws MyException{
             try {
                FileReader reader = new FileReader("G:\\myfile\\struts.txt");  
                 Scanner in = new Scanner(reader);  
                 System.out.println(in.next());
            } catch (FileNotFoundException e) {
                //e 保存異常信息
                throw new MyException("文件沒有找到--01",e);
            }  
        }

        public void g() throws MyException{
            try {
                f();
            } catch (MyException e) {
                //e 保存異常信息
                throw new MyException("文件沒有找到--02",e);
            }
        }

        public static void main(String[] args) {
            Test t = new Test();
            try {
                t.g();
            } catch (MyException e) {
                e.printStackTrace();
            }
        }
    }

運行結(jié)果:


    com.test9.MyException: 文件沒有找到--02
        at com.test9.Test.g(Test.java:31)
        at com.test9.Test.main(Test.java:38)
    Caused by: com.test9.MyException: 文件沒有找到--01
        at com.test9.Test.f(Test.java:22)
        at com.test9.Test.g(Test.java:28)
        ... 1 more
    Caused by: java.io.FileNotFoundException: G:\myfile  \struts.txt (系統(tǒng)找不到指定的路徑。)
        at java.io.FileInputStream.open(Native Method)
        at java.io.FileInputStream.<init>(FileInputStream.java:106)
        at java.io.FileInputStream.<init>(FileInputStream.java:66)
        at java.io.FileReader.<init>(FileReader.java:41)
        at com.test9.Test.f(Test.java:17)
        ... 2 more

如果在程序中,去掉 e,也就是:throw new MyException(“文件沒有找到 –02″);

那么異常信息就保存不了,運行結(jié)果如下:

    com.test9.MyException: 文件沒有找到--02
        at com.test9.Test.g(Test.java:31)
        at com.test9.Test.main(Test.java:38)

PS:其實對于異常鏈鄙人使用的也不是很多,理解的不是很清楚,望各位指正?。。?!

七、異常的使用誤區(qū)

首先我們先看如下示例:該實例能夠反映 Java 異常的不正確使用(其實這也是我剛剛學(xué) Java 時寫的代碼)?。?


    OutputStreamWriter out = null;
            java.sql.Connection conn = null;
            try {            //   ---------1
                Statement stat = conn.createStatement();
                ResultSet rs = stat.executeQuery("select *from user");
                while (rs.next()){
                    out.println("name:" + rs.getString("name") + "sex:"
                            + rs.getString("sex"));
                }
                conn.close();         //------2
                out.close();
            } 
            catch (Exception ex){    //------3
                ex.printStackTrace();    //------4
            }

1、———–1

對于這個 try…catch 塊,我想他的真正目的是捕獲 SQL 的異常,但是這個 try 塊是不是包含了太多的信息了。這是我們?yōu)榱送祽卸B(yǎng)成的代碼壞習(xí)慣。有些人喜歡將一大塊的代碼全部包含在一個 try 塊里面,因為這樣省事,反正有異常它就會拋出,而不愿意花時間來分析這個大代碼塊有那幾塊會產(chǎn)生異常,產(chǎn)生什么類型的異常,反正就是一簍子全部搞定。這就想我們出去旅游將所有的東西全部裝進一個箱子里面,而不是分類來裝,雖不知裝進去容易,找出來難?。。。∷袑τ谝粋€異常塊,我們應(yīng)該仔細分清楚每塊的拋出異常,因為一個大代碼塊有太多的地方會出現(xiàn)異常了。

結(jié)論一:盡可能的減小try塊?。?!

2、——–2

在這里你發(fā)現(xiàn)了什么?異常改變了運行流程??!不錯就是異常改變了程序運行流程。如果該程序發(fā)生了異常那么 conn.close(); out.close();是不可能執(zhí)行得到的,這樣勢必會導(dǎo)致資源不能釋放掉。所以如果程序用到了文件、Socket、JDBC 連接之類的資源,即使遇到了異常,我們也要確保能夠正確釋放占用的資源。這里 finally 就有用武之地了:不管是否出現(xiàn)了異常,finally 總是有機會運行的,所以 finally 用于釋放資源是再適合不過了。

結(jié)論二:保證所有資源都被正確釋放。充分運用 finally 關(guān)鍵詞。

3、———3

對于這個代碼我想大部分人都是這樣處理的,(LZ 也是)。使用這樣代碼的人都有這樣一個心理,一個 catch 解決所有異常,這樣是可以,但是不推薦!為什么!首先我們需要明白 catch 塊所表示是它預(yù)期會出現(xiàn)何種異常,并且需要做何種處理,而使用 Exception 就表示他要處理所有的異常信息,但是這樣做有什么意義呢?

這里我們再來看看上面的程序?qū)嵗?,很顯然它可能需要拋出兩個異常信息, SQLException 和 IOException。所以一個 catch 處理兩個截然不同的 Exception 明顯的不合適。如果用兩個 catch,一個處理 SQLException、一個處理 IOException 就好多了。所以:

結(jié)論三:catch 語句應(yīng)當盡量指定具體的異常類型,而不應(yīng)該指定涵蓋范圍太廣的 Exception 類。 不要一個 Exception 試圖處理所有可能出現(xiàn)的異常。

4、———4

這個就問題多多了,我敢保證幾乎所有的人都這么使用過。這里涉及到了兩個問題,一是,捕獲了異常不做處理,二是異常信息不夠明確。

4.1、捕獲異常不做處理,就是我們所謂的丟棄異常。我們都知道異常意味著程序出現(xiàn)了不可預(yù)期的問題,程序它希望我們能夠做出處理來拯救它,但是你呢?一句 ex.printStackTrace() 搞定,這是多么的不負責(zé)任對程序的異常情況不理不顧。雖然這樣在調(diào)試可能會有一定的幫助,但是調(diào)試階段結(jié)束后呢?不是一句 ex.printStackTrace() 就可以搞定所有的事情的!

那么怎么改進呢?有四種選擇:

1、處理異常。對所發(fā)生的的異常進行一番處理,如修正錯誤、提醒。再次申明 ex.printStackTrace() 算不上已經(jīng)“處理好了異?!?

2、重新拋出異常。既然你認為你沒有能力處理該異常,那么你就盡情向上拋吧?。?!

3、封裝異常。這是 LZ 認為最好的處理方法,對異常信息進行分類,然后進行封裝處理。

4、不要捕獲異常。

4.2、異常信息不明確。我想對于這樣的:java.io.FileNotFoundException: ………信息除了我們 IT 人沒有幾個人看得懂和想看吧!所以在出現(xiàn)異常后,我們最好能夠提供一些文字信息,例如當前正在執(zhí)行的類、方法和其他狀態(tài)信息,包括以一種更適合閱讀的方式整理和組織 printStackTrace 提供的信息。起碼我公司是需要將異常信息所在的類、方法、何種異常都需要記錄在日志文件中的。

所以:

結(jié)論四:既然捕獲了異常,就要對它進行適當?shù)奶幚?。不要捕獲異常之后又把它丟棄,不予理睬。 不要做一個不負責(zé)的人。

結(jié)論五:在異常處理模塊中提供適量的錯誤原因信息,組織錯誤信息使其易于理解和閱讀。

對于異常還有以下幾個注意地方:

六、不要在finally塊中處理返回值。

七、不要在構(gòu)造函數(shù)中拋出異常。

八、try…catch、throw、throws

在這里主要是區(qū)分 throw 和 throws。

throws 是方法拋出異常。在方法聲明中,如果添加了 throws 子句,表示該方法即將拋出異常,異常的處理交由它的調(diào)用者,至于調(diào)用者任何處理則不是它的責(zé)任范圍內(nèi)的了。所以如果一個方法會有異常發(fā)生時,但是又不想處理或者沒有能力處理,就使用 throws 吧!

而 throw 是語句拋出異常。它不可以單獨使用,要么與 try…catch 配套使用,要么與 throws 配套使用。


    //使用throws拋出異常
        public void f() throws MyException{
             try {
                FileReader reader = new FileReader("G:\\myfile\\struts.txt");  
                 Scanner in = new Scanner(reader);  
                 System.out.println(in.next());
            } catch (FileNotFoundException e) {
                throw new MyException("文件沒有找到", e);    //throw
            }  

        }

九、總結(jié)

其實對于異常使用的優(yōu)缺點現(xiàn)在確實存在很多的討論。例如:http://www.cnblogs.com/mailingfeng/archive/2012/11/14/2769974.html 。這篇博文對于是否需要使用異常進行了比較深刻的討論。LZ實乃菜鳥一枚,不能理解異常深奧之處。但是有一點LZ可以肯定,那就是異常必定會影響系統(tǒng)的性能。

異常使用指南(摘自:Think in Java)

應(yīng)該在下列情況下使用異常。

1、在恰當?shù)募墑e處理問題(在知道該如何處理異常的情況下才捕獲異常)。

2、解決問題并且重新調(diào)用產(chǎn)生異常的方法。

3、進行少許修補,然后繞過異常發(fā)生的地方繼續(xù)執(zhí)行。

4、用別的數(shù)據(jù)進行計算,以代替方法預(yù)計會返回的值。

5、把當前運行環(huán)境下能做的事情盡量做完。然后把相同(不同)的異常重新拋到更高層。

6、終止程序。

7、進行簡化。

8、讓類庫和程序更加安全。(這既是在為調(diào)試做短期投資,也是在為程序的健壯做長期投資)

更多閱讀:Java提高篇—–異常(一)。

上一篇:hashCode下一篇:強制類型轉(zhuǎn)換