}
class Product {
String name;
int price;
Product(String n, int p) {
name=n;
price=p;
}
String getName() {
return name;
}
int getPrice() {
return price;
} }
主題 13:例外 (Exception)
所謂「例外」,就是當程式碼編輯完,在編譯期間沒有出現錯誤訊息,但在程式執行時卻發生錯誤,
這種錯誤又稱為執行時期錯誤(Runtime error)。
在編譯程式或執行程式時常會遇到各種不同錯誤,以致無法正常完成工作。研發軟體時最容易遇到三 種錯誤(Bug):語法錯誤、執行時期錯誤、邏輯錯誤。
1. 語法錯誤
語法錯誤是初學者最容易犯的錯誤。在編譯過程中,系統常能立即指出此種錯誤的所在,並要求程式
設計者修正後才能正式執行。這樣錯誤最容易解決,只要熟悉語法多多練習就可以減少錯誤產生。
2. 執行時期錯誤
程式在執行時,因為輸入資料不符合、在計算過程分母為 0、磁碟中無此檔案存在、陣列的索引值超 出陣列宣告範圍…等,使得程式中斷執行。這種錯誤的問題在編譯時,並不會發生,被 Java 稱為「例 外」,而 Java 也提供了例外處理的方式來解決問題。
3. 邏輯錯誤
邏輯錯誤是最難找出的,尤其在大型應用程式最為明顯。程式在執行過程並沒有出現錯誤,也會有執 行結果,甚至有時候結果是正確的。除非你仔細觀察,多人多次測試,否則不見得會發現。因此誤信 其執行結果,往往造成很大損失。有些系統提供偵錯(Debug)工具,用來協助找出錯誤之處。若沒 有偵錯工具,就只能自己設定偵測點,輸出目前主要變數內容是否如預測結果,以推測可能錯誤之處,
再仔細研讀程式,尋找邏輯上錯誤之處,加以修正。
範例 13_例外_01 import java.util.Scanner;
public class Ch01 {
static Scanner s=new Scanner(System.in);
public static void main(String[] args) {
int x,y;
System.out.print("輸入分子: ");
x=s.nextInt();
System.out.print("輸入分母: ");
y=s.nextInt();
System.out.println(x+"/"+y+"="+(x/y));
} }
除了捕捉 Java 拋出的例外物件,還可以利用關鍵字 throw 自行拋出例外物件。而若拋出的例外物件非 系統能自行捕捉到,譬如自訂類別的例外,則需在方法宣告列後面利用關鍵字 throws 註明例外類別名 稱,以便在指定的方法中拋出例外。
範例 13_例外_02_自訂例外類別 import java.util.Scanner;
public class Ch02 {
static Scanner s=new Scanner(System.in);
//若拋出的例外物件非系統能自行捕捉到,譬如自訂類別的例外物件,需在此註明 public static void main(String[] args) throws MyException
{ int x,y;
System.out.print("輸入分子: ");
x=s.nextInt();
System.out.print("輸入分母: ");
y=s.nextInt();
if(y==0)
throw new MyException("嘿嘿嘿~分母不可為零喔!");
System.out.println(x+"/"+y+"="+(x/y));
} }
class MyException extends Exception {
MyException(String str) {
super(str); //呼叫父類別的建構子 }
}
進行例外處理是不希望程式中斷。而是希望程式能捕捉錯誤並繼續執行,若錯誤是使用者輸入不正確 資料所造成的,可以要求使用者輸入正確資料再繼續執行,或者不處理使用者輸入資料繼續做其他工 作。
Java 使用 try … catch … finally 敘述來解決例外處理,它的方式是將被監視的敘述區段寫在 try 大括 號內,當程式執行到 try 內的敘述有發生錯誤時,會逐一檢查捕捉(catch)該錯誤,以便執行該 catch 內敘述。最後不管是否有符合 catch,都會執行最後的 finally 敘述區段。例外處理的格式如下:
try {
預期可能發生例外的敘述 }
catch(例外物件) {
對應的處理程序 }
finally //可有可無 {
無論例外是否發生都會處理的程序 }
範例 13_例外_03_例外處理 1 import java.util.*;
public class Ch03 {
public static void main(String args[]) {
for(int i=1; i<=3; i++) //允許三次嘗試 {
try //可能發生例外的程式區塊
{ int a, b;
Scanner s=new Scanner(System.in);
System.out.print("請輸入分子: ");
a=s.nextInt();
System.out.print("請輸入分母: ");
b=s.nextInt();
System.out.println(a+"/"+b+"="+(a/b));
break; //若運算成功,即跳出迴圈 }
catch(ArithmeticException e) //針對捕捉到的例外物件,作相對應的回應 {
System.out.println("運算錯誤! 分母不可為零!");
}
catch(InputMismatchException e) {
System.out.println("格式錯誤! 輸入須為整數!");
}
System.out.println();
if(i==3)
System.out.println("錯誤嘗試過多! 程式跳出!");
} } }
範例 13_例外_04_例外處理 2 import java.util.Scanner;
public class Ch04 {
static Scanner s=new Scanner(System.in);
//因有使用 catch 語法捕捉自訂類別的例外物件,故 throws 敘述便可省略 public static void main(String[] args) //throws MyException
{ try
{
int x,y;
System.out.print("輸入分子: ");
x=s.nextInt();
System.out.print("輸入分母: ");
y=s.nextInt();
if(y==0)
throw new MyException();
System.out.println(x+"/"+y+"="+(x/y));
}catch(MyException e) {
System.out.println("嘿嘿嘿~分母不可為零喔!");
} } }
class MyException extends Exception {
MyException() {
super(); //呼叫父類別的建構子 }
}