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''); }