week6 異常處理

2017-07-19(三)

Java week6 異常處理

  • 在處理程序時,遇到bug是必經之路,但是看著編譯器顯示著各種錯誤、異常,有時會感到很受挫,因為不曉得錯誤在何處,是網路的問題、電腦的記憶體、輸入輸出有誤、運行有問題、亦或是邏輯本身就有錯,而程序員必須有系統的查找錯誤,不能貪圖用ad hoc change(短平快)的方式查找錯誤。

  • 因此,本章介紹異常的處理方式、異常的分類與分級、如何自行定義異常、他的優點何在,下半部設介紹程序的測試與調試。

  • 大綱:

    • 異常處理

    • 異常的分類

    • 受檢異常(checked Exception)

    • 自行定義的異常

    • 優點

    • 斷言及程序的測試

    • 程序的調試

異常:

1.定義:又稱例外、差錯、為例,是對應著Java運行錯誤的處理機制

2.基本寫法:

try{ 语句组}

catch(Exception ex){ 异常处理语句组;}

代碼範例:ExceptionForNum.java

import java.io.*;
public class ExceptionForNum 
{
    public static void main(String[] args) 
    {
        try{
            BufferedReader in = new BufferedReader(
                new InputStreamReader( System.in ) );
            System.out.print("Please input a number: ");
            String s = in.readLine();
            int n = Integer.parseInt( s );
        }catch(IOException ex){
            ex.printStackTrace();
        }catch(NumberFormatException ex){
            ex.printStackTrace();
        }
    }
}

3.第41行就是try要做什麼語句,第47,50行,表示異常補取,前者是輸入輸出的異常;後者是數字格式的異常

異常的處理:

  • 拋出(throw)異常

  • 運行時系統在調用棧(stack)查找:从生成异常的方法开始进行回溯,直到找到

  • 捕獲(catch)異常的代碼

如同上述代碼,catch可以0~多個,finally語句是可有可無

異常的分類:

  • Throwable,分成兩個子類,第一是Error(JVM 錯誤); 第二是Exception異常

  • Error:所謂Error指的是嚴重的錯誤情況。當Error產生時,其行為和Exceptio類似,但是try catch區塊沒有辦法攔下它們,最後會由JVM來處理Error,並中斷執行緒的執行。像OutOfMemoryError,StackOverflowError都是Error的子類別。

  • Exception:底下有很多種情況,像是RuntimeException, IOException(底下又有EOFException, FileNotFoundException)

Exception類:

構造方法:

  • public Exception();

  • public Exception(String message);

  • Exception(String message, Throwable cause) ;

方法:

  • getMessage()

  • getCause()

  • printStackTrace()

finally語句:

public class TestTryFinally {
    public static String output = "";
    public static void foo(int i) {
        try {
            if (i == 1) {
                throw new Exception();
            }
            output += "1";
        } catch(Exception e) {
            output += "2";
            return;
        } finally {
            output += "3";
        }
        output += "4";
    }
    public static void main(String args[]) {
        foo(1);
        System.out.println(output + " ");
        System.out.print(",,,,,");
        foo(0);
        System.out.println(output);
    }
}

Output

23 ,,,, 23134

首先,foo(1)會throw出exception,然後catch後,接著是finally; 在foo(0)階段,承接foo(1)的output,但是因為沒有進入if判斷式,所以進入finally,接著進行到外圍,也就是==output +=4==。

問題:為什麼在foo(1)時,==output +=4==不會運行到呢?

受檢異常(checked Exception)

Exception分為兩種,一種不能明確處理(RuntimeException),另一種是可以明確處理(checked Exception), 後者又稱受檢異常,要求明確語法處理,具體來說,要麼catch、要麼throws。

代碼連結

因為拋出e,直接先做catch,所以==System.out.println("====After====")== 這行沒跑出來。

自行定義異常:

创建用户自定义异常时

  • (1) 继承自Exception类或某个子Exception类

  • (2) 定义属性和方法,或重载父类的方法

在拋出與捕獲異常時,還得傳遞給調用者,這時會有很多狀況,以下是重新拋出異常與異常的鏈接情形

  1. throw e :將當前的catch異常再次拋出

  2. throw new Exception("some message"):重新生成一個異常,然後再次拋出

  3. throw new Exception("some message",e):重新生成并抛出一个新异常,该异常中包含了当前异常的信息

光是列點,還無法理解當中的意涵,透由代碼來理解當中的運作比較清楚,

輸出結果:

f

e

a

d

something wrong MyAppException: invalid id

b

cause DataHouseException: cannot find the id

代碼解釋:

  1. 一開始從main出發,進入try語句後,先印出f,接著進入 BankATM.GetBalanceInfo()方法中

  2. 接著,從line31開始讀,進入try後,在印出e來,接著進入 DataHouse.FindData()方法中

  3. 從line17開始,判斷ID的範圍,但是找不到之後,進入else內,然後印出a,接著在line26中,丟出 DataHouseException(屬於剛剛談的情形二)

  4. 這裡的關鍵在於,line26丟出 DataHouseException 後,line40 去catch 丟出來的DataHouseException,並且印出d,然後再丟出MyAppException(屬於情形三,提供原因並且丟出異常e )

  5. line7去捕捉這個異常e ,在line8 中印出剛剛給的cause與原先的結合,顯示是 MyAppException: invalid id

  6. 接著印出b後,這裡注意不是再次印出MyAppException,而是要再往更上層查找,也就是lin26的 DataHouseException,且印出的cause 加上 "cannot find the id"

問題:

在步驟6的方法,與code中的line11,

System.out.println("cause "+  e.getCause())

為什麼是要往更上層查找,這個原因是什麼?

總結:

  • Markdown Plus的軟體真好用,顏色背景、字體辨識、source code的標記、顏色標記,甚至還有雷達圖,果然付費後的價值真的不一樣。

  • 在輸出筆記時,如果只是搬運ppt,沒有消化理解,用自己方法說出,其實沒啥用處,慢下來把代碼看懂,反而對內容消化更深,而且自已講過一遍代碼,會發現更深層的問題,畢竟,要輸出筆記,總得讓別人看得懂,不能太偷懶。

  • 加上github的連結後,更容易講解代碼,這比截圖還更有意思,至於後半段的部分,程序的測試與調試在後續補上。 :muscle:

Last updated

Was this helpful?