Ch11 JAVA的例外處理 物件導向程式設計(II)
大綱 Java的例外處理 例外處理的程式敘述 丟出例外 自訂Exception類別 2018/11/13
Java的例外處理 Java語言的「例外」(Exception)是指產生了例外物件,這是一種例外事件,在程式執行時,發生不正常執行狀態時所產生事件的物件,「例外處理」(Handling Exceptions)就是在處理這些例外事件。 例外處理的目的是為了讓程式能夠更「強壯」(Robust),當程式遇到不尋常情況,也不會造成程式「崩潰」(Crashing),進而導致整個系統當機。 2018/11/13
例外處理的架構-說明 Java的例外處理架構是一種您丟我撿的架構,當JVM執行Java程式有錯誤發生時,就會產生例外物件,有了例外,JVM開始尋找是否有方法可以處理。 一種是在方法上加上例外處理的程式敘述來處理例外(在第13-2節說明)。 或是將例外丟給其它方法來處理(在第13-3節說明)。 2018/11/13
例外處理的架構-圖例 2018/11/13
例外處理的架構-過程 在執行Java程式時,從main()方法呼叫methodA()方法,接著呼叫methodB()方法,最後呼叫methodC()方法,呼叫過程是存入稱為「呼叫堆疊」(Call Stack),這是一種先進後出的資料結構,用來儲存呼叫方法的狀態資料,以便返回還原成呼叫時的狀態。 當methodC()方法發生錯誤產生例外物件A,JVM倒過來找尋方法是否擁有例外處理,首先是methodC()和methodB(),因為沒有例外處理,所以例外會傳遞給methodA(),在此方法擁有例外處理A,所以可以處理例外物件A。 2018/11/13
Throwable類別-說明 在Java產生的例外物件屬於Throwable類別或其子類別的實例,Throwable類別擁有2個直接繼承的子類別,如下所示: Error類別:其子類別屬於JVM的嚴重錯誤,這種錯誤會導致程式終止執行,所以並沒有辦法使用例外處理來處理這種錯誤。 Exception類別:其子類別是各種例外物件,也是例外處理可以處理的部分,事實上,部分例外物件也是一種錯誤,只是錯誤沒有嚴重到需要終止程式執行,例外處理就是在防止程式終止執行,並且作一些補救操作。 2018/11/13
Throwable類別-說明 Exception類別擁有子類別RuntimeException,在此類別的子類別是一些常見的例外,如下表所示: 2018/11/13
例外處理的程式敘述-區塊架構 Java語言例外處理程式敘述分為try、catch、finally三個程式區塊,可以處理特定的例外物件,如下所示: try { ……… } catch(ExceptionType e) { // 例外處理 ……… } finally { ……… } 2018/11/13
例外處理的程式敘述-try程式區塊 try程式區塊 在try區塊的程式碼檢查是否產生例外,當例外產生時,就會丟出指定例外類型的物件。 2018/11/13
例外處理的程式敘述-catch程式區塊 catch程式區塊 在try程式區塊的程式碼如果丟出例外,Java程式需要準備一到多個catch程式區塊處理不同類型的例外,傳入參數e是例外類型的物件(繼承自Throwable類別),可以取得例外的相關資訊,其相關方法如下表所示: 2018/11/13
範例1:例外處理_除以零 b1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { String s1 = t1.getText(); int i1 = Integer.parseInt(s1); int i2 = Integer.parseInt(t2.getText()); int ans = i1 / i2; t3.setText(Integer.toString(ans)); } } ); Ch12_01.java 2018/11/13
範例1(續) b1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { try String s1 = t1.getText(); int i1 = Integer.parseInt(s1); int i2 = Integer.parseInt(t2.getText()); int ans = i1/i2; t3.setText(Integer.toString(ans)); } catch(ArithmeticException e) t3.setText(e.getMessage()); } ); Ch12_02.java 2018/11/13
例外處理的程式敘述-finally程式區塊 2018/11/13
同時處理多種例外 在Java程式的try/catch/finally程式敘述,可以使用多個catch程式區塊來同時處理多種例外物件,如下所示: try{ } catch( ArithmeticException e ) { ……… } catch( ArrayIndexOutOfBoundsException e ) finally { } 2018/11/13
使用throw程式敘述-說明 Java程式碼可以使用throw指令丟出例外,其語法如下所示: throw ThrowableObject; 上述ThrowableObject是繼承自Throwable類別的物件,表示丟出例外物件。 2018/11/13
使用throw程式敘述-範例 例如:在Java程式丟出ArithmeticException例外物件,如下所示: throw new ArithmeticException("值為0"); 上述程式碼使用new運算子建立例外物件,建構子參數是讓getMessage()方法取得的例外說明字串。 2018/11/13
範例2:方法本身丟出例外 public class Ch12_04 { // 主程式 { // 主程式 public static void main(String[] args) { // 例外處理程式敘述 try // 取得參數字串 { int value = Integer.parseInt(args[0]); if ( value == 0 ) // 丟出ArithmeticException例外 throw new ArithmeticException("值為0"); } catch( ArithmeticException e ) { // 處理ArithmeticException例外 System.out.println("例外說明: "+e.getMessage()); System.out.print("例外原因: "); e.printStackTrace(); finally { System.out.println("錯誤處理結束"); } 2018/11/13
在方法丟出例外 在某些情況,雖然方法會產生例外,但是我們並不希望在此方法建立例外處理(通常是為了集中處理例外事件),此時,可以將例外丟出,讓呼叫此方法的其它方法接手處理例外,如下所示: static double cal(double a,double b,double c) throws IllegalArgumentException { ……… throw new IllegalArgumentException( "c不能是0!"); ……… } 2018/11/13
範例3:在方法丟出例外,由別的呼叫者處理 2018/11/13 public class Ch12_05 { // 類別方法: 計算a*b/c的值 static double cal(double a, double b, double c) throws IllegalArgumentException { double value; if ( c == 0 ) { // 丟出IllegalArgumentException例外 throw new IllegalArgumentException("c不能是0!"); } else { value = a*b/c; if ( value < 0 ) throw new IllegalArgumentException("運算結果小於0"); } return value; // 主程式 public static void main(String[] args) { double result; try // 取得參數值 { double a = Double.parseDouble(args[0]); double b = Double.parseDouble(args[1]); double c = Double.parseDouble(args[2]); result = cal(a, b, c); // 呼叫方法 System.out.println("計算結果: " + result); } catch( IllegalArgumentException e ) { // 處理IllegalArgumentException例外 System.out.println("例外說明: "+e.getMessage()); System.out.print("例外原因: "); e.printStackTrace(); catch( ArrayIndexOutOfBoundsException e ) { System.out.println(e.getMessage()); 2018/11/13
自訂Exception類別 在Java程式除了使用現成Exception類別的例外,也可以自訂Exception類別建立應用程式所需的例外類別,如下所示: class UserException extends Exception { int data; public UserException(int data) { this.data = data; } public String getMessage() { return ("錯誤! 出價太多次: " + data); } } 2018/11/13
範例4:自訂Exception類別 2018/11/13 // 自訂Exception類別, 繼承Exception類別 class UserException extends Exception { // 變數宣告 int data; // 建構子 public UserException(int data) { this.data = data; } // 覆寫getMessaeg()方法 public String getMessage() { return ("錯誤! 出價太多次: " + data); } } // 主程式類別 public class Ch12_06 { // 主程式 public static void main(String[] args) { try { int i; for ( i = 0; i < 5; i++ ) { if (i == 3) // 丟出自訂的例外 throw new UserException(3); System.out.println("出價次數: " + i); } catch( UserException e) { // 處理自訂的例外 System.out.println("例外說明: "+e.getMessage()); System.out.print("例外原因: "); e.printStackTrace(); return; finally { System.out.println("錯誤處理結束!"); } System.out.println("程式結束!"); 2018/11/13