Practical Java(重點版)之異常處理

 以下是學習《Practical Java(重點版)》的筆記。

1.  認識異常控制流(exception control flow)機制。當異常發生時,會轉入到以下三種的處理方式之一:

a).catch block(捕獲區段)

b).finally block(終結區段)

c).calling method(調用端)

這三種方式都是異常表現的goto行爲。

如果程序在try段拋出異常會發生以下事情:

a).如果同時存在catch和finally段的話,則控制流先轉向catch,然後轉向finally。

b).如果沒有catch的話,則轉向finally段。

如果程序正常退出或者異常退出,則該方法創建的對象都將會自動解決引用。

2.  絕對不可輕忽異常(Never ignore an exception)。如果一個線程的異常發生了,但是你未捕獲處理的話,那麼該線程將被中斷。當異常發生的時候,我們可以做的事情如下:

1). 捕捉並處理它,防止它進一步傳播(propagate)。

2). 捕捉並再次拋出它,這麼一來它會被傳播給調用端。

3). 捕捉它,然後拋出一個新異常給調用端。

4) .不捕捉這個異常,聽任它傳播給調用端。

對捕獲的異常,最好是記錄到日誌中,採用printStackTrace()的方式將其寫到日誌中,方便今後的查找問題。異常最好是捕獲,不能夠什麼都不做。

3.  千萬不要隱藏異常。

public class HideExectionTest {

  static void hide() throws Exception {

  try {

         throw new Exception("hide");//1

      } catch (Exception e) {

         throw new Exception("catch");//2

      } finally {

         throw new Exception("Finally");//3

      }

  }

 

  public static void main(String[] args) {

      try {

         hide();

      } catch (Exception e) {

         System.out.println("In main : cathc exception " + e.getMessage());

      }

  }

}

這種情況就隱藏了異常,輸出結果:

In main : cathc exception Finally

原因:1的異常被2覆蓋了,而2的異常又被3覆蓋了,所以只返回了3的處理異常。在這個時候可以自定義一個異常處理類,然後收集處理的異常信息,最後再將該異常拋出。這樣就避免了隱藏異常。

4.  throws子句的缺點

throws(拋擲)子句是一種語言機制,用來列出「可從某個函數傳至外界」的所有可能異常。編譯器強迫你必須在函數中捕捉這些被列出的異常,否則就得在該函數的throws子句中聲明它們。throws子句用來向函數調用者發出預警,告知將會產生哪些異常。這是一項非常有用的語言特性,爲函數用戶提供非常有價值的信息。然而這個特性也有副作用,你必須心理有數。

5. 全面理解throws子句

提供throws 子句的用意在於,提醒函數調用者,告知可能發生的異常。如果父類方法throws了異常,那麼子類在覆寫此方法時候:可以不throws異常;可以throws出父類方法異常類的派生異常;如果在子類中出現了其他異常,則必須在子類中捕獲處理,不能夠傳遞。

如下:

class Test{

    public void key() throws FileNotFoundException{ 

    }

}

子類:

class SubTest1 extends Test{

    public void key() throws FileNotFoundException{

    }

}

class SubTest2 extends Test{

    public void key(){

    }

}

class SubTest3 extends Test{

    public void key() throws FileNotFoundException{

    try {

           …

       } catch (NumberFormatException e) {

       }

    }

}

6. 使用finally避免資源泄露

無論是否發生異常,finally中的內容始終會執行。

7. 不要在try段中返回

在try finally搭配中,最好不在try中使用return,break,continue,會導致代碼閱讀性不好。

以下是個例子:

public class TryFinally {

    static int test1() {

       try {

           return 1;

       } catch (Exception e) {

           return 2;

       }

    }

 

    static int test2() {

       try {

           return 3;

       } catch (Exception e) {

           return 0;

       } finally {

           return 4;

       }

    }

 

    public static void main(String[] args) {

       System.out.println(test1());

       System.out.println(test2());

    }

}

輸出結果:1

                  4

8. 將try/catch段設置於循環之外

如果客戶使用無JIT能力的JVM時候,將try/catch放到循環中,會導致效率下降。不啓動JIT可以減少內存使用。

如果你想在不啓動JIT 的情況下執行名爲Test.class 的文件,請下這個命令

Java - Djava.compiler=NONE Test

這會使得在執行程序Test 時,JVM 的JIT 能力被抑制。

9.  不要將異常用於流程控制

10.不要每逢出錯就使用異常

11. 在構造方法(constructors)中拋出異常

構造方法支持throws子句。

12. 拋出異常之前先將對象恢復爲有效狀態(valid state)

和事務有很大的相似之處,都是萬一失敗的話,以前提交的動作該如何處理。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章