此 文件已有 新版本!
假設今天你受命開發一個程式庫,例如一個存取檔案的程式好了,你也許會這麼寫:
import java.io.*;
public class FileUtil {
public static String readText(String file) {
String text = null;
FileReader reader = null;
try {
reader = new FileReader(file);
...
}
catch(FileNotFoundException ex) {
System.out.println("找不到檔案" + file);
}
return text;
}
....
}
public class FileUtil {
public static String readText(String file) {
String text = null;
FileReader reader = null;
try {
reader = new FileReader(file);
...
}
catch(FileNotFoundException ex) {
System.out.println("找不到檔案" + file);
}
return text;
}
....
}
由 於操作檔案讀取的過程中,有許多方法可能丟出受檢例外(Checked Exception),你可能如上使用try..catch加以處理,在catch中以主控台方式輸出錯誤訊息,但問題在於,你並不知道你的程式庫會用在 什麼環境,是文字模式?視窗模式?或是Web應用程式?直接在catch中寫死處理處理例外或輸出錯誤訊息的方式,是一件不符合需求的方式。
如果你的方法設計流程中,發生例外時,當時的上下文環境並不知道該如何 處理(例如你並不知道程式庫會用在什麼環境下時),那麼你可以丟出例外,讓呼叫你的方法的客戶端來處理。例如:
import java.io.*;
public class FileUtil {
public static String readText(String file) throws FileNotFoundException {
String text = null;
FileReader reader = new FileReader(file)
...
return text;
}
....
}
public class FileUtil {
public static String readText(String file) throws FileNotFoundException {
String text = null;
FileReader reader = new FileReader(file)
...
return text;
}
....
}
操作物件的過程中如果丟出受檢例外,而你不使用try..catch處 理,則表示目前環境資訊不足以處理例外,必須由屆時使用該方法的客戶端依當時環境資訊進行處理,為了告訴編譯器這件事實,則必須在方法上使用throws 宣告會丟出例外,那麼編譯器才會讓你通過編譯。
如果是非受檢例外(Unchecked Exception),由於你可以自行選擇是否處理例外,不使用try..catch處理時也不用特別在方法上使用throws宣告,當你不處理非受檢例 外,例外自動往外傳播。
當例外發生時,你可以使用try..catch處理當時環境下所可以作的錯誤處理,對於當時環境下無法決定如何處理的部份,可以丟出去給屆時的客戶端處 理。如果你想先處理部份事項再丟出,則一個例子如下:
import java.io.*;
public class FileUtil {
public static String readText(String file) throws IOException {
String text = null;
FileReader reader = null;
try {
reader = new FileReader(file);
...
}
catch(FileNotFoundException ex) {
// Logging 或 ex.printstackTrace()
// 其它處理
throw ex;
}
finally {
if(reader != null) {
try {
reader.close();
}
catch(IOException ex) {
// Logging 或 ex.printstackTrace()
// 其它處理
throw ex;
}
}
}
return text;
}
....
}
public class FileUtil {
public static String readText(String file) throws IOException {
String text = null;
FileReader reader = null;
try {
reader = new FileReader(file);
...
}
catch(FileNotFoundException ex) {
// Logging 或 ex.printstackTrace()
// 其它處理
throw ex;
}
finally {
if(reader != null) {
try {
reader.close();
}
catch(IOException ex) {
// Logging 或 ex.printstackTrace()
// 其它處理
throw ex;
}
}
}
return text;
}
....
}
在進行完部份錯誤處理之後,你可以使用throw將例外再丟出,當你在流程中丟出例外,就 直接跳離原有的流程。如果流程正常執行,最後一定要執行的動作可以放在finally區塊中。
一個有趣的問題是,如果程式撰寫的流程中先return了,而你也有寫finally區塊,那finally區塊還會執行嗎?答案是肯定的, finally區塊會先執行完後,再執行return。例如下面這個程式會先顯示「finally...」再顯示「1」:
public
class Main {
public static int test(boolean flag) {
try {
if(flag) {
return 1;
}
}
finally {
System.out.println("finally...");
}
return 0;
}
public static void main(String[] args) {
System.out.println(test(true));
}
}
public static int test(boolean flag) {
try {
if(flag) {
return 1;
}
}
finally {
System.out.println("finally...");
}
return 0;
}
public static void main(String[] args) {
System.out.println(test(true));
}
}