close

23   例外處理(Exception handling)-1

撰寫Java原始碼、編譯並執行,期間會碰到各種問題,有些屬於程式語法錯誤、程式邏輯錯誤,有些屬於作業系統、硬體錯誤等。這些錯誤有些必須在程式中預作處置,有些則非程式可以控制的。

如果只以Java程式本身的問題來分類,可分為編譯時期的錯誤、執行時期的錯誤及程式邏輯錯誤。

[編譯期錯誤]

Java編譯時出現(或發現)的錯誤,例如程式碼拼字錯誤、語法錯誤及後述的Checked Exception等屬之。因為這些錯誤造成程式無法完成編譯,當然也就不能執行了。

[執行期錯誤]

顧名思義就是在執行時期出現的錯誤。例如超出陣列範圍、除以0等,造成程式執行中斷。這些錯誤也可能是因為程式邏輯錯誤所導致。

[程式邏輯錯誤]

程式雖然在編譯期及執行期沒有發生錯誤而中斷,但其執行結果並不是預期的結果,就可能是程式設計的邏輯錯誤。

不論是硬體、作業系統及程式問題,這些出現的異常,可分為錯誤(Error)及例外(Exception)

 

[23-1異常的分類]

圖23-1

 

 

[錯誤(Error)]

為系統本身發生之錯誤等屬之,程式碼置不置入處理方式皆可。

[例外(Exception)]

除數為0及要讀取的檔案不存在等,導致程式無法繼續執行之異常屬之。可分為非受檢例外及受檢例外。

[非受檢例外(Unchecked Exception)]

屬於程式執行時期(Runtime)可能發生各種例外,如除以0,或陣列指標超出範圍等,因這部分屬於程式邏輯部分,可於程式中事前進行檢查防範,可不必置入例外檢查處理程式碼,如要置入亦非不可。如有置入例外處理程式碼,執行時期發生例外時,則依例外處理程式碼處置。編譯程式不檢查非受檢例外(unchecked exception)是否有置入例外處理程式碼。如果程式沒有撰寫例外處理程式碼,即不會捕捉此一異常,會一直往上傳遞至main(),回報至System.err,並會呼叫printStackTrace列印顯示錯誤訊息。

Unchecked Exception

例外名稱例

產生原因

ArithmeticException

運算式產生的例外,例如:除數為0

ArrayIndexOutOfBoundsException

陣列的索引值指定錯誤,例如:超出索引值

ArrayStoreException

指定陣列內容錯誤時產生的錯誤

ClassCastException

類別轉型錯誤

IndexOutOfBoundsException

索引使用時超出範圍,這個類別是ArrayIndexOutOfBoundException的父類別

IllegalArgumentException

呼叫方法時,傳遞錯誤的參數

NullPointerException

使用物件時,該物件的參考值為null

NumberFormatException

將字串轉為文字時,產生無法轉換的錯誤

SecurityException

企圖違反安全性的限制

 

[受檢例外(Checked Exception)]

屬於程式執行時期可能發生各種例外,且必須於程式中進行處理,即所謂checked exception,如沒有或找不到要讀取得檔案等。受檢例外錯誤沒有置入例外處理的程式碼,將會發生編譯錯誤,須追加例外處理的程式碼後再編譯。

Checked Exception

例外名稱例

產生原因

ClassNotFoundException

找不到指定的類別,可以發生在使用某個類別的方法,但卻找不到該方法所屬的類別

FileNotFoundException

找不到指定的檔案

CloneNotSupportException

在類別中使用clone()方法,但該類別未實作「Cloneable」介面

InterruptedException

當某個執行緒中斷時,而另一個執行緒試圖使用「interrupt()」方法來中斷已停止執行的執行緒

IOException

檔案、網路的輸出、入錯誤時產生的例外

   

 

  

[23-2內建(標準)例外處理類別]

Java內建例外處理類別體系,皆繼承自Throwable類別,程式可直接引用。

 

表格列舉:Java系統內建例外處理類別之父子類別關係表 

 

 

 

T

h

r

o

w

a

b

l

e

(

)

Error

(處不處理皆可)

VirtualMachineError

StackOverflowError

OutOfMemoryError

AssertionError

LinkageError

ExceptionInInitializerError

NoClassDefFoundError

E

x

c

e

p

t

i

o

n

Unchecked Exception

(處不處理

皆可)

RuntimeException

ArithmeticException

NullPointerException

IllegalStateException

IndexOutOfBoundsException

ClassCastException

IllegalArgumentException

Checked

Exception

(須處理)

IOException

EOFException

FileNotFoundException

ClassNotFoundException

SQLException

InterruptedException

 

 

 

圖例(部分)

圖23-2

 

 

[23-3例外處理方式]

[23-3-1使用try/catch/finally區塊]

由拋出例外的方法自行捕捉並處理時使用。

[格式]

try{ 可能會發生例外的程式區塊 }

catch(TypeOneException e1){ 例外1處理區塊 }

catch(TypeTwoException e2){ 例外2處理區塊 }

catch(TypeThreeException e3){ 例外3處理區塊 }

.................

finally{ 無論是否發生例外皆要處理的區塊 }

 

圖23-3

 

 

可能發生例外的程式碼置於try區塊,而將所有可能的例外處理程式碼,條列於各個catch區塊,理論上可能發生n種例外,就必須要有ncatch區塊對應捕捉並處理。finally則不論發生例外與否,皆會執行的程式區塊,即便finally述句前之trycatch區塊有return敘述,仍會執行完finally述句後才會執行return返回。編譯程式會檢查checked exception有無try/catch/finally區塊,沒有設定時會使程式編譯失敗。但unchecked exception則不須指定,如要指定亦可。

catch之例外類別須由孫類別->子類別->父類別之次序由上往下排列,否則排在後面較下階之例外類別可能執行不到,在編譯階段會發現此一錯誤(compile error)。多個下位例外類別也可只以一個上位類別來總括處理,例如catch只指定「exception」類別,其下ArithmeticExceptionIndexOutOfBoundsException等皆歸其catch。沒有繼承之直屬關係者,可以任意順序擺放。

 

[checked exception] <主方法><未置入try/catch/finally區塊>

import java.io.*;

public class Exceptiontcfm1 {

public static void main(String[] args)  {

  System.out.println("Opening FileInputStream");
    FileInputStream f = new FileInputStream("abc.txt"); 
      //檔案輸出入類別,將在後述章節說明
    //假設發生FileNotFoundException
    System.out.println("File Opened");
  } 
}

編譯結果:錯誤

C:\js>javac Exceptiontcfm1.java

Exceptiontcfm1.java:5: error: unreported exception FileNotFoundException; must b

e caught or declared to be thrown

    FileInputStream f = new FileInputStream("abc.txt");

                        ^

1 error

 

*checked exception須置入例外處理程式碼。

 

備註:

引用Java系統內建類別(分別存放在不同類型之套件中)或第三方類別時,必須使用import敘述,但其中java.lang套件則可省略,java.lang套件包含MathSystemString等。

有輸出入錯誤時,例外處理須使用import java.io.*;

 

[checked exception] <主方法> <使用try/catch/finally區塊>

import java.io.*;

public class Exceptiontcfm2{

public static void main(String[] args)  {

try {
          System.out.println("Opening FileInputStream");
          FileInputStream f = new FileInputStream("abc.txt");
            //檔案輸出入類別,將在後述章節說明
          //假設發生FileNotFoundException
          System.out.println("File Opened");
} 
catch (FileNotFoundException e1) {
          System.out.println("FileNotFoundException caught");
} 
catch (Exception e2) {
          System.out.println("Exception caught");
} 
finally {
          System.out.println("Execute finally block");
}
  }
}

編譯、執行結果:

C:\js>javac Exceptiontcfm2.java

C:\js>java Exceptiontcfm2

Opening FileInputStream

FileNotFoundException caught

Execute finally block

 

[checked exception]<非主方法> <未置入try/catch/finally區塊>

import java.io.*;

public class Exceptiontcfm3 {

public static void main(String[] args)  {

    Tcfg3 aa = new Tcfg3();

  aa.tcfm3();
  } 
}
 

class Tcfg3 {

publicvoid tcfm3() {

  System.out.println("Opening FileInputStream");
    FileInputStream f = new FileInputStream("abc.txt"); 
    //假設發生FileNotFoundException
    System.out.println("File Opened");
  } 
}

編譯結果:錯誤

C:\js>javac Exceptiontcfm3.java

Exceptiontcfm3.java:12: error: unreported exception FileNotFoundException; must

be caught or declared to be thrown

    FileInputStream f = new FileInputStream("abc.txt");

                        ^

1 error

 

*checked exception須置入例外處理程式碼。

 

 

[checked exception] <非主方法> <使用try/catch/finally區塊>

import java.io.*;

public class Exceptiontcfm4 {

public static void main(String[] args)  {

    Tcfg4 aa = new Tcfg4();

  aa.tcfm4();
  } 

}

 

class Tcfg4{

void tcfm4() {

try{

          System.out.println("Opening FileInputStream");
          FileInputStream f = new FileInputStream("abc.txt"); 
          //假設發生FileNotFoundException
          System.out.println("File Opened");
} 
catch (FileNotFoundException e1) {
          System.out.println("FileNotFoundException caught");
} 
catch (Exception e2) {
          System.out.println("Exception caught");
} 
finally {
          System.out.println("Execute finally block");
}
  }
}

執行結果:

C:\js>javac Exceptiontcfm4.java

C:\js>java Exceptiontcfm4

Opening FileInputStream

FileNotFoundException caught

Execute finally block

 

[unchecked exception]<主方法> <未置入try/catch/finally區塊>

由命令列輸入兩個1~3的整數。

import java.io.*;

class MainException1 {

  public static void main(String args[]) {

    if(args.length <= 1) {

       System.out.println("請從命令列輸入兩個1~3的整數");

       System.exit(1);

    }

   int m = 12;

   int n = Integer.parseInt(args[0]);

    m = m / n;

    int[] x = {1,2,3};

    int y = x[Integer.parseInt(args[1])-1];       

    System.out.println("程式結束!");

   }

}

編譯、執行結果:

C:\js>javac MainException1.java

C:\js>java MainException1 0 3

Exception in thread "main" java.lang.ArithmeticException: / by zero

        at mainException1.main(mainException1.java:10)

 

C:\js>java mainException1 3 5

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4

        at mainException1.main(mainException1.java:12)

 

C:\js>java mainException1 2 2

程式結束!

 

不使用try/catch/finally區塊,則由JVM進行例外處理。

 

[unchecked exception]<主方法> <使用try/catch/finally區塊>

由命令列輸入兩個1~3的整數,

import java.io.*;

class mainException2 {

  public static void main(String args[]) {

    if(args.length <= 1) {

       System.out.println("請從命令列輸入兩個1~3的整數");

       System.exit(1);  }

   try{ int m = 12;

        int n = Integer.parseInt(args[0]);

        m = m / n;

        int[] x = {1,2,3};

        int y = x[Integer.parseInt(args[1])-1];  }

   catch(ArrayIndexOutOfBoundsException f) {

        System.out.println("Out of Range" + f.getMessage()); }

   catch(RuntimeException e) {

        System.out.println(e.getMessage());   }

   finally{

        System.out.println("程式結束!");   }

  }

}

編譯、執行結果:

C:\js>javac MainException2.java

C:\js>java MainException2 0 3

/ by zero

程式結束!

 

C:\js1>java MainException2 3 5

Out of Range4

程式結束!

 

C:\js>java mainException2 2 2

程式結束!

 

*非主方法執行結果會和主方法執行結果一樣。 


[23-3-2 throws預告例外]

throws定義於方法名稱之同一列,列出該方法可能出現的異常。目的是告訴要呼叫該方法的方法要處理這些異常,例如以try/catch處理。throws通常定義於非主方法。

import java.io.*;

class ThrowsClass {

  void divideArray(int s, int t) throws RuntimeException,

    ArrayIndexOutOfBoundsException { //非主方法定義throws

    int m = 12;

    int n = s;

    m = m / n;

    int[] x = {1,2,3};

    int y = x[t];  }  }

 

class MainException3 {

  public static void main(String[] args) {   //主方法定義try/catch/finally

    if(args.length <= 0) {

       System.out.println("請從命令列輸入兩個數字0134");

       System.exit(1); }

    ThrowsClass m = new ThrowsClass();

   try{ m.divideArray(Integer.parseInt(args[0]),Integer.parseInt(args[1]));  }

   catch(ArrayIndexOutOfBoundsException f) {

        System.out.println("Out of Range" + f.getMessage());   }

   catch(RuntimeException e) { System.out.println(e.getMessage());  }

   finally{ System.out.println("程式結束!"); }

  }

}

執行結果:

C:\js>java MainException3 0 1

/ by zero

程式結束!

 

C:\js1>java MainException3 3 4

Out of Range4

程式結束!

 

圖23-4

  

[23-3-3 throw刻意拋出例外類別]

throw於方法內之try區塊中使用,刻意拋出例外,並由後續之catch區塊捕捉處理。使用throw必須自訂異常訊息。throw可配合throws使用,便於主方法呼叫。

throw並非由實際執行時發生異常才拋出例外,而是程式中在某種條件下刻意拋出之例外。

import java.io.*;

class ThrowsClass2 {

  void divideArray(int s, int t) {

    int m = 12;

    if(s == 0) throw new RuntimeException("除數為0"); //設定例外訊息

    int n = s;   

    m = m / n;

    int[] x = {1,2,3};

    if (t > 3) throw new ArrayIndexOutOfBoundsException("超出陣列範圍");

    int y = x[t];  }  }

 

class MainException4 {

  public static void main(String args[]) {

    if(args.length <= 0) {

       System.out.println("請從命令列輸入兩個數字0134");

       System.exit(1);   }

    ThrowsClass2 m = new ThrowsClass2();

   try{ m.divideArray(Integer.parseInt(args[0]),Integer.parseInt(args[1]));  }

   catch(ArrayIndexOutOfBoundsException f) {

        System.out.println(f.getMessage());   }

   catch(RuntimeException e) { System.out.println(e.getMessage());   }

   finally{ System.out.println("程式結束!");   }

  }

}

執行結果:

C:\js>java MainException4 0 1

除數為0

程式結束!

 

C:\js1>java MainException4 3 4

超出陣列範圍

程式結束!

 

因並非由例外處理機制進行處理,沒自訂訊息時會顯示null,則無法得知例外訊息。

import java.io.*;

class ThrowsClass3 {

  void divideArray(int s, int t) {

    int m = 12;

    if(s == 0) throw new RuntimeException();//不設定例為訊息

    int n = s;   

    m = m / n;

    int[] x = {1,2,3};

    if (t > 3) throw new ArrayIndexOutOfBoundsException();

    int y = x[t];  }  }

class MainException5 {

  public static void main(String args[]) {

    if(args.length <= 0) {

       System.out.println("請從命令列輸入兩個數字0134");

       System.exit(1);    }

    ThrowsClass3 m = new ThrowsClass3();

    try{ m.divideArray(Integer.parseInt(args[0]),Integer.parseInt(args[1]));  }

    catch(ArrayIndexOutOfBoundsException f) {

        System.out.println(f.getMessage());   }

    catch(RuntimeException e) { System.out.println(e.getMessage());   }

    finally{ System.out.println("程式結束!");   }

  }

}

執行結果:

C:\js>java mainException5 0 1

null

程式結束!

 

C:\js>java mainException5 3 4

null

程式結束! 

 

 

[23-4認清throwsthrow]

throws只是列舉該方法可能發生的例外種類,呼叫該方法時,呼叫者應該要對那些列舉的例外進行處理,如果為主方法時,亦應對那些列舉的例外進行處理,即應要設定有try/catch等。因為如果沒設定有catch,不論有無throws,一律交由JVM處理例外,如下2例:

 

[設定有throws]

import java.io.*;

public class mainException4 {

  public static void main(String args[]) throws ArrayIndexOutOfBoundsException {

    if (args.length != 1) {

      System.out.println("請輸入一個陣列元素次序值");

      System.exit(1);

      }

      int n = Integer.parseInt(args[0]);     

      int x[] = {3,6,9,12,15};

      System.out.println("陣列元素" + n + " = " + x[n-1] + "");

      System.out.println("程式結束。");

  }

}

JVM(及系統)丟出例外訊息:

C:\js>java mainException4 6

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5

        at mainException4.main(mainException4.java:10)

 

[沒設定有throws]

import java.io.*;

public class mainException5 {

  public static void main(String args[]) {

    if (args.length != 1) {

      System.out.println("請輸入一個陣列元素次序值");

      System.exit(1);

      }

      int n = Integer.parseInt(args[0]);     

      int x[] = {3,6,9,12,15};

      System.out.println("陣列元素" + n + " = " + x[n-1] + "");

      System.out.println("程式結束。");

  }

}

JVM丟出例外訊息:

C:\js>java mainException5 6

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5

        at mainException5.main(mainException5.java:10)

 

有某一書籍說有tryfinallycatch時要設定有throws,亦是錯誤的,同上述沒catch時一律由JVM處理。

[沒設定throws]

import java.io.*;

class mainException1_1 {

  public static void main(String args[]) {

    if(args.length <= 1) {

       System.out.println("請從命令列輸入兩個1~3的整數");

       System.exit(1);

      }

   try{

        int m = 12;

        int n = Integer.parseInt(args[0]);

        m = m / n;

        int[] x = {1,2,3};

        int y = x[Integer.parseInt(args[1])-1];       

       }

   finally{

        System.out.println("程式結束!");

        }

  }

}

JVM丟出例外訊息:

C:\js>java mainException1_1 0 3

程式結束!

Exception in thread "main" java.lang.ArithmeticException: / by zero

        at mainException1_1.main(mainException1_1.java:11)

[設定有throws]

import java.io.*;

class mainException1_2 {

  public static void main(String args[]) throws RuntimeException,

      ArrayIndexOutOfBoundsException{

    if(args.length <= 1) {

       System.out.println("請從命令列輸入兩個1~3的整數");

       System.exit(1);

      }

   try{

        int m = 12;

        int n = Integer.parseInt(args[0]);

        m = m / n;

        int[] x = {1,2,3};

        int y = x[Integer.parseInt(args[1])-1];       

       }

   finally{

        System.out.println("程式結束!");

       }

  }

}

JVM丟出例外訊息:

C:\js>java mainException1_2 0 3

程式結束!

Exception in thread "main" java.lang.ArithmeticException: / by zero

        at mainException1_2.main(mainException1_2.java:12) 

 

 

[23-5例外處理各類格式整理]

將上述說明以表格方式及簡單例子整理如下:

例外處理各類格式整理:

編號

格式

說明

(1)

try-catch-finally

try區塊偵測拋出異常;catch區塊捕捉、處理異常;finally區塊則不論有無異常皆會處理。

(2)

try-catch

try區塊偵測拋出異常;catch區塊捕捉、處理異常。

(3)

try-finally

try區塊偵測拋出異常;因無catch區塊,捕捉、處理異常交給上一層(call)處理,如一直交到最上層皆無處哩,則由JVM處理,發出錯誤訊息並結束程式;finally區塊則不論有無異常皆會處理。

(4)

throws

throws則預告這個method可能會發生異常,call方要置入異常處理程序。有無throws並不影響程式編譯及執行,只是作為提醒之用。call方如無置入異常處理程序,則交給上一層或JVM處理。

(5)

throw

並非由JVM發現之異常,throw可主動刻意拋出異常種類,

拋出之後仍須由異常處理程序處理,沒處理時仍交給上一層或JVM處理。

 

 

[23-5-1使用try/catch/finally格式]

說明:

*將try/catch/finally置入可能出現異常的地方,即可能發生問題的方法之內。

try區塊發生問題時,由catch區塊依異常類型加以處理。

finally區塊是不論發生異常與否皆會執行的程式碼。

catchfinally區塊執行完畢後,不會回到異常程式碼後方繼續執行。

finally區塊執行後,會繼續執行其後之程式碼(如果有的話)

*因在此方法內就已經處理了,不會再將例外提交給上層(例如主方法)或是JVM了。

[主方法例]

import java.io.*;

public class DivideByZeroM1{

  public static void main(String[] args){

   try{

       int x=10, y=0, z=0;

       z=x/y;

       System.out.println("程式結束M1-1");

      }

catch (ArithmeticException e){

   System.out.println(e.getMessage()+"---M1");

}

finally{

System.out.println("程式結束M1-2");

      }

    System.out.println("程式結束M1-3");

  }

}

執行結果:

C:\js>java DivideByZeroM1

/ by zero---M1

程式結束M1-2

程式結束M1-3

 

[一般方法例]

說明:

*物件呼叫方法如發生異常,經該方法異常處理後,仍會回到呼叫程式碼後之繼續處理。

import java.io.*;

public class DivideByZeroM2{

  public static void main(String[] args){

    DivideByZeroG2 G2 = new DivideByZeroG2();

    G2.methodG2();

    System.out.println("程式結束M2");

  }

}

 

class DivideByZeroG2{

  public void methodG2(){

   try{

       int x=10, y=0, z=0;

       z=x/y;

       System.out.println("程式結束G2-1");

      }

catch (ArithmeticException e){

   System.out.println(e.getMessage()+"---G2");

}

finally{

System.out.println("程式結束G2-2");

      }

    System.out.println("程式結束G2-3");

  }

}

執行結果:

C:\js>C:\js>java DivideByZeroM2

/ by zero---G2

程式結束G2-2

程式結束G2-3

程式結束M2

 

 

[23-5-2使用try/catch格式]

基本上同try/catch/finally,只是少了finally區塊的處理。

[主方法例]

import java.io.*;

public class DivideByZeroM3{

  public static void main(String[] args){

   try{

       int x=10, y=0, z=0;

       z=x/y;

System.out.println("程式結束M3-1");

      }

catch (ArithmeticException e){

   System.out.println(e.getMessage()+"---M3");

}

System.out.println("程式結束M3-2");

  }

}

執行結果:C:\js>java DivideByZeroM3

/ by zero---M3

程式結束M3-2

[一般方法例]

import java.io.*;

public class DivideByZeroM4{

  public static void main(String[] args){

    DivideByZeroG4 G4 = new DivideByZeroG4();

    G4.methodG4();

System.out.println("程式結束M4");

  }

}

 

class DivideByZeroG4{

  public void methodG4(){

   try{

       int x=10, y=0, z=0;

       z=x/y;

System.out.println("程式結束G4-1");

      }

catch (ArithmeticException e){

   System.out.println(e.getMessage()+"---G4");

}

System.out.println("程式結束G4-2");

  }

}

執行結果:C:\js>java DivideByZeroM4

/ by zero---G4

程式結束G4-2

程式結束M4

 

 

[23-5-3使用try/finally格式]

[主方法例]

*沒有catch時,異常會在執行完finally後拋給上一層,本例為JVM顯示訊息。

import java.io.*;

public class DivideByZeroM5{

  public static void main(String[] args){

   try{

       int x=10, y=0, z=0;

       z=x/y;

System.out.println("程式結束M5-1");

      }

finally{

System.out.println("程式結束M5-2");

      }

    System.out.println("程式結束M5-3");

  }

}

執行結果:C:\js>java DivideByZeroM5

程式結束M5-2

Exception in thread "main" java.lang.ArithmeticException: / by zero

        at DivideByZeroM5.main(DivideByZeroM5.java:6)

 

[一般方法例]

*沒有catch時,異常會在執行完finally後拋給上一層,但上一層之主方法亦未處理,故再拋給上一層即為JVM顯示訊息。

import java.io.*;

public class DivideByZeroM6{

  public static void main(String[] args){

    DivideByZeroG6 G6 = new DivideByZeroG6();

    G6.methodG6();

System.out.println("程式結束M6");

  }

}

 

class DivideByZeroG6{

  public void methodG6(){

   try{

       int x=10, y=0, z=0;

       z=x/y;

System.out.println("程式結束G6-1");

      }

finally{

System.out.println("程式結束G6-2");

      }

    System.out.println("程式結束G6-3");

  }

}

執行結果:C:\js>java DivideByZeroM6

程式結束G6-2

Exception in thread "main" java.lang.ArithmeticException: / by zero

        at DivideByZeroG6.methodG6(DivideByZeroM6.java:14)

        at DivideByZeroM6.main(DivideByZeroM6.java:5)

 

 

[23-5-4 使用throws]

throws句置於方法宣告之方法名及參數之後、{}之前,是預告該方法可能出現之異常,欲呼叫該方法的方法應置入異常處理程式碼,如try/catch/finally

[主類別內一般方法例]

*都是同一人所編碼,應不須使用throws

import java.io.*;

public class DivideByZeroM7{

  public static void main(String[] args) {

   try{

      DivideByZeroM7 M7 = new DivideByZeroM7();

M7.methodM7();

}

   catch(ArithmeticException e) {

System.out.println(e.getMessage()+"---M7-1"); 

}

finally{ System.out.println("程式結束M7-2");

}

System.out.println("程式結束M7-3");

  }

public void methodM7() throws ArithmeticException {

    int x=10, y=0, z=0;

   z=x/y;

System.out.println("程式結束M7-4");

  }

}

執行結果:C:\js>java DivideByZeroM7

/ by zero---M7-1

程式結束M7-2

程式結束M7-3

 

 

[不同類別的一般方法例]

和上例[主類別內一般方法例]相同用法,為throws主要使用方式。

import java.io.*;

public class DivideByZeroM8{

  public static void main(String[] args) {

   try{

      DivideByZeroG8 G8 = new DivideByZeroG8();

G8.methodG8();

}

   catch(ArithmeticException e) {

System.out.println(e.getMessage()+"---M8-1"); 

}

finally{ System.out.println("程式結束M8-2");

}

System.out.println("程式結束M8-3");

  }

}

 

class DivideByZeroG8{

  public void methodG8() throws ArithmeticException {

    int x=10, y=0, z=0;

   z=x/y;

System.out.println("程式結束M8-4");

  }

}

執行結果:C:\js>java DivideByZeroM8

/ by zero---M8-1

程式結束M8-2

程式結束M8-3

 

[無異常處理程式碼例]

*不置入try/catch/finally,因屬unchecked exception故可編譯成功,但因無異常處理程式碼,故拋給上層處理,即JVM拋出例外訊息、程式中止。

import java.io.*;

public class DivideByZeroM9{

  public static void main(String[] args) {

    DivideByZeroG9 G9 = new DivideByZeroG9();

G9.methodG9();

System.out.println("程式結束M9-1");

}

}

 

class DivideByZeroG9{

  public void methodG9() throws ArithmeticException {

    int x=10, y=0, z=0;

   z=x/y;

System.out.println("程式結束M9-2");

  }

}

編譯及執行結果:

C:\js>javac DivideByZeroM9.java

 

C:\js>java DivideByZeroM9

Exception in thread "main" java.lang.ArithmeticException: / by zero

        at DivideByZeroG9.methodG9(DivideByZeroM9.java:13)

        at DivideByZeroM9.main(DivideByZeroM9.java:5)

 

 

[23-5-5使用throw]

[主類別try(throw)/catch/finally]

try區塊中使用throw自行拋出例外。

import java.io.*;

public class DivideByZeroM10{

  public static void main(String[] args) {

   try{ int x=10, y=0, z=0;

       if (y==0){

         throw new ArithmeticException("除數為0");

       }

       z=x/y;

        System.out.println("程式結束M10-1");

    }

   catch(ArithmeticException e) {

System.out.println(e.getMessage()+"---M10-2"); 

}

finally{ System.out.println("程式結束M10-3");

}

System.out.println("程式結束M10-4");

  }

}

執行結果:C:\js>java DivideByZeroM10

除數為0---M10-2

程式結束M10-3

程式結束M10-4

 

[主類別throws-try(throw)/catch/finally]

同上例,但於方法中使用throws預告拋出異常,並無特別用處。

import java.io.*;

public class DivideByZeroM11{

  public static void main(String[] args) throws ArithmeticException {

   try{ int x=10, y=0, z=0;

        if (y==0){

         throw new ArithmeticException("除數為0");

       }

       z=x/y;

        System.out.println("程式結束M11-1");

    }

   catch(ArithmeticException e) {

System.out.println(e.getMessage()+"---M11-2"); 

}

finally{ System.out.println("程式結束M11-3");

}

System.out.println("程式結束M11-4");

  }

}

執行結果:C:\js>java DivideByZeroM11

除數為0---M11-2

程式結束M11-3

程式結束M11-4

 

[同一類別主方法呼叫一般方法]

import java.io.*;

public class DivideByZeroM12{

  public static void main(String[] args) {

   try{

        DivideByZeroM12 M12 = new DivideByZeroM12();

        M12. methodM12();

       }

   catch(ArithmeticException e){

        System.out.println(e.getMessage()+"---M12-1");

       }

finally{ System.out.println("程式結束M12-2");

}

System.out.println("程式結束M12-3");

  }

void methodM12(){

    int x=10, y=0, z=0;

    if (y==0)

     throw new ArithmeticException("除數為0");

   z=x/y;

    System.out.println("程式結束M12-4");

  }

}

執行結果:C:\js>java DivideByZeroM12

除數為0---M12-1

程式結束M12-2

程式結束M12-3

 

[不同類別呼叫一般方法]

import java.io.*;

public class DivideByZeroM13{

  public static void main(String[] args) { //可放置異常處理

    DivideByZeroM13 M13 = new DivideByZeroM13();

    M13. methodM13();

}

  void methodM13(){ //可放置異常處理

    try{

        DivideByZeroG13 G13 = new DivideByZeroG13();

        G13. methodG13();

       }

   catch(ArithmeticException e){

        System.out.println(e.getMessage()+"---M13-1");

       }

finally{ System.out.println("程式結束M13-2");

}

System.out.println("程式結束M13-3");

}

}

 

class DivideByZeroG13{

void methodG13(){   //可放置異常處理

    int x=10, y=0, z=0;

    if (y==0)

     throw new ArithmeticException("除數為0");

   z=x/y;

    System.out.println("程式結束G13-4");

  }

}

執行結果:C:\js>java DivideByZeroM13

除數為0---M13-1

程式結束M13-2

程式結束M13-3 

 

arrow
arrow

    祈泊 發表在 痞客邦 留言(0) 人氣()