java異常——捕獲異常+再次拋出異常與異常鏈

來源:互聯網
上載者:User

標籤:不同   com   code   cat   ase   ogg   lex   類型   unknown   

【0】README

0.1) 本文描述+原始碼均 轉自 core java volume 1, 旨在理解 java異常——捕獲異常+再次拋出異常與異常鏈 的相關知識;

【1】捕獲異常相關

1.1)如果某個異常發生的時候沒有再任何地方進行捕獲, 那程式就會運行終止: 並在控制台上列印出異常資訊 , 其中包括異常的類型堆棧的內容;
1.2)要想捕獲一個異常, 必須設定 try/catch 語句塊:

  • 1.2.1)如果在try語句塊中拋出了一個在 catch子句中聲明的異常類, 那麼
    • case1)程式將跳過try 語句塊的其餘代碼;
    • case2)程式將執行 catch 子句中 的處理器代碼;
  • 1.2.2)如果在try語句塊中沒有拋出任何異常, 那麼程式將跳過 catch子句;
  • 1.2.3)如果方法中的任何代碼拋出了一個在 catch 子句中沒有聲明的異常類型, 那麼這個方法就會立刻退出;

1.3)看個荔枝: (看一個讀取文本的程式碼以示範捕獲異常的處理過程)

public void read(String filename){    try    {        InputStream in = new FileInputStream(filename);  // 建立輸入資料流        int b;        while((b=in.read()) != -1)            process input    }    catch(IOException exception)    {        exception.printStackTrace(); // 列印棧軌跡;    }}

對上述代碼的分析(Analysis):

  • A1)需要注意的是, try 語句中的大多數代碼都很容易理解, 讀取並處理文本行, 直到遇到檔案結束符為止;(read 方法可能拋出一個IOException異常)
  • A2)在這種情況下, 將跳出整個while迴圈, 進入 catch子句, 並產生一個 棧軌跡;

1.4)對於一個普通 的程式來說, 處理以上的對異常處理的方法外,還有其他方法嗎?

  • 1.4.1)通常, 最好的選擇是: 什麼也不做, 而是將異常傳遞給調用者;如果read方法出現了錯誤, 那就讓read方法的調用者去處理。
  • 1.4.2)如果採用這種方式, 就必須聲明這個方法可能拋出一個 IOException(將異常傳遞給調用者);
public void read(String filename) throws IOException{        InputStream in = new FileInputStream(filename);  // 建立輸入資料流        int b;        while((b=in.read()) != -1)            process input}

Attention)編譯器嚴格地執行 throws 說明符。 如果調用了一個拋出已檢查異常的方法, 就必須對它進行處理, 或者將它繼續進行傳遞;
1.5)對於以上兩種處理異常的方法, 哪種 方法更好呢?(method1:自己處理(在可能發生異常的函數中添加try/catch 語句塊);method2:將異常傳遞(throw)給調用者,調用者處理)

  • 1.5.1)通常, 應該捕獲那些知道如何處理的異常, 而將那些不知道怎麼處理的異常繼續進行傳遞;如果想傳遞一個異常, 就必須在方法的首部添加一個throws 說明符, 以便告知調用者這個方法可能會拋出異常;
  • 1.5.2)閱讀API後, 以便知道這個方法可能會拋出哪種異常, 然後再決定是自己處理, 還是添加到 throws 列表中;

Attention)以上規則有個例外: 前面提到, 如果編寫一個 覆蓋超類的方法, 而這個方法又沒有拋出異常, 那麼這個方法就必須捕獲方法代碼中出現的每一個已檢查異常。不允許在子類的 throws 說明符中出現超過超類方法所列出的異常類範圍;(也就是說父類方法沒有拋出異常,你子類方法也不準拋出異常,只能自己添加 try/catch 語句塊自己處理)

【2】捕獲多個異常

2.1)在一個try 語句塊中可以捕獲多個異常, 並對不同類型的異常做出不同的處理。可以按照下列方式為每個異常類型使用一個單獨的 catch 子句;

try{}catch(FileNotFoundException e){}catch(UnknownHostException e){}catch(IOException e){}

2.2)要想獲得異常對象 的更多資訊: 可以試著使用 e.getMessage() 得到詳細的錯誤資訊, 或者使用 e.getClass().getName(); 得到異常對象 的實際類型;
2.3)合并catch 子句: 在 java SE7中, 同一個 catch 子句中可以捕獲多個異常類型。 例如, 假設對應缺少檔案和 未知主機異常的動作是一樣的, 就可以合并catch 子句:

try{}catch(FileNotFoundException | UnknownHostException e){}catch(IOException e){}

Attention)

  • A1)只有當捕獲的異常類型彼此間不存在子類別關係時 才需要這個特性;
  • A2)捕獲多個異常時, 異常變數隱含為 final變數。例如, 不能在以下子句體中為 e 賦不同的 值;
    catch(FileNotFoundException || UnknownHostException e) {}
  • A3)捕獲多個異常不僅會讓你的代碼看起來簡單, 還會更高效。產生的位元組碼只包含一個對應公用catch 子句的代碼塊;
【3】再次拋出異常與異常鏈

3.1)在catch子句中可以拋出一個異常, 這樣做的目的是 改變異常類型;

  • 3.1.1)看個荔枝:
try{}catch(SQLException e){    throw new ServletException("data error : " + e.getMessage());}

對以上代碼的分析(Analysis):

  • A1)這裡, ServletException 用帶有異常資訊文本的構造器來構造;
  • A2)不過, 可以有一種更好的方法, 並且將原始異常設定為新異常的原因:
try{}catch(SQLException e){    Throwable se = new ServletException("database error");    se.initCause(e);    throw se;}
  • A3)當捕獲到這個異常時, 就可以使用下面的語句重新得到 原始異常:
Throwable e = se.getCause();

Attention)強烈建議使用這種封裝技術, 這樣可以讓使用者拋出子系統中的進階異常, 而不會丟失原始異常的小細節; (推薦使用 strongly recommended)

Hint)

  • H1)如果在一個方法中發生了一個已檢查異常,而不允許拋出它, 那麼封裝技術就十分有用。 我們還可以捕獲這個已檢查異常, 並將它封裝成一個 運行時異常;
  • H2)有時候, 你可能只想記錄一個異常,再將它重新拋出, 而不做任何改變:
try{    access the database}catch(Exception e){    logger.log(level, message, e);    throw e;}
  • H3)在Java SE7 之前, 將上述代碼放入下述方法中, 會出現一個問題;
public void updateRecord() throws SQLException
  • 因為, java 編譯器查看catch 塊中的 throw 語句, 然後查看e的類型, 會指出這個方法可以拋出任何Exception而不僅僅是 SQLException;
  • H4)java se 7之後(編譯器檢測文法合法): 編譯器會跟蹤到 e 來自於try塊中, 假設這個 try 塊中僅有 的已檢查異常 是 SQLException執行個體, 另外,假設e在catch塊中未改變, 將外圍方法聲明為 throws SQLException 就是合法的;

java異常——捕獲異常+再次拋出異常與異常鏈

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.