1.處理(handle) : 直接捕獲異常並處理。
處理異常動作:使用異常處理區塊(try-catch-finally)
- try:區塊內放置可能拋出異常語句。
- catch:區塊內處理異常的動作,動作步驟為產生異常後,try區塊停止動作,JVM尋找相關的catch區塊。可能會有多個catch區塊,異常會交給第一個符合的catch 區塊處理。
- finally:無論try 或 catch 是否會執行,finally區塊一定會執行
處理異常規則:
try之後必須接著catch 或是 finally。catch和finally可以一起出現,但必須至少有一個。
在多個catch 區塊的情況下,經驗法則為從最具體排到最一般。
選擇處理的優點:在本地端直接處理,容易找到發生問題點,方法調用者不須多寫處理。
選擇處理的缺點:缺少通用性,無法選擇其他的處理方式,因為必須多寫處理的代碼因此增加該方法的複雜度。
2.聲明(declare) : 聲明該方法拋出異常,讓呼叫端接手處理。
聲明異常動作:在方法宣告中加上 throws ExceptionName
聲明異常的規則:
- 必須聲明方法中可能拋出的可檢測異常(checked exception),非檢測異常(unchecked exception)不是必須的,可聲明也可以不聲明。
- 聲明異常類別可以是其異常子類。
選擇聲明原因:
- 需要傳送異常發送到系統其他部份。
- 無法在本地端處理異常。
3.選擇處理或是聲明異常
經驗法則:盡可能處理異常,若無法處理才聲明異常。
4.標準異常處理選項
1.紀錄異常相關訊息
- 使用標準輸出或錯誤流
- 開發自定義類
- 使用java 紀錄api (java.util.logging)
2.要求客戶端輸入訊息
透過GUI讓client 選擇下一步
3.使用預設值或替換數據
- 簡單情況將預設值設定為靜態常量加在程式碼中。
- 複雜情況可將預設值紀錄在配置文件(Properties)中,並在發生問題時載入。
4.將控制轉移到應用程序的其他部份
- 簡單情況提取catch 處理方法
try {
result = bufferReader.readLine();
} catch (IOException e) {
handleReadLineException();
}
}
private void handleReadLineException(){
// do handle exception for read line
}
- 複雜情況開發一個異常處理類別,來集中處理應用程序代碼
5.將異常轉換成其他形式
- 可提供更適當的上下文用來描述異常
private void connect(String ip) throws ServerConnectionException
{
try {
//some exception
} catch (IOException e) {
throw new ServerConnectionException ("specify message from Server Connect", e);
}
}
6.準備停止系統
- 有打開的文件就關閉
- 有連接的資源就關閉
- 儲存必要資訊
- 通知其他部份應用程序即將結束
7.重試操作
- 等待一段時間後重試操作
try {
connect();
} catch (IOException e) {
retryConnect();
}
private void retryConnect()
{
try {
Thread.sleep(10000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try{
connect();
}catch(IOException e){
//retry connect
}
}
8.替換或恢復操作
- 如無法儲存在伺服器上就改為存在本機硬碟
try {
saveToServer();
} catch (IOException e) {
saveToLocalDisk();
}
private void saveToLocalDisk(){
}
9.忽略問題
- 當異常對系統其他部份沒有影響,如調用 I/O stream的關閉方法
private FileReader mFileReader;
...
...
try {
mFileReader.close();
} catch (IOException e)
{
e.printStackTrace();
}
5.解決異常建議事項
- 盡可能處理異常:盡可能處理,除非條件不予許再考慮聲明異常。
- 具體問題具體解決:需要為特定類型的問題建立特定的處理區塊。
- 紀錄可能影響應用程序運行的異常:可以採取永久的方式紀錄影響應用程序的異常,可以幫助處理問題
- 根據情況將異常轉換為業務上下文:建立異常的成本不高,可以考慮為特定的問題轉換特定的異常。
6.解決異常不建議事項
- 不要忽略異常
try {
printStream = new PrintStream(new File("./error_record"));
System.setOut(printStream);
printStream.println("error message");
} catch (FileNotFoundException e)
{//do nothing here}
- 不要使用覆蓋式異常處理
try { printStream = new PrintStream(new File("./error_record")); System.setOut(printStream); printStream.println("error message"); } catch (Exception e) { // do something } - 不要將特定異常轉為一般異常
try { printStream = new PrintStream(new File("./error_record")); System.setOut(printStream); printStream.println("error message"); } catch (IOException e) { throw new Exception(exceptionMessage); } - 不要處理能夠避免的異常(使用判斷式取代拋出異常)
-
使用 if(printStream != null){ printStream.println("error message"); } 取代 try{ printStream.println("error message"); }catch(NullPointerException e){ System.out.println(''PrintStream is null''); }