大家好,歡迎來到樂字節小樂的Java技術分享園地

在Java中,凡是可能拋出異常的語句,都可以用try ... catch
捕獲。把可能發生異常的語句放在try { ... }
中,然后使用catch
捕獲對應的Exception
及其子類。
多catch語句
可以使用多個catch
語句,每個catch
分別捕獲對應的Exception
及其子類。JVM在捕獲到異常后,會從上到下匹配catch
語句,匹配到某個catch
后,執行catch
代碼塊,然后不再繼續匹配。
簡單地說就是:多個catch
語句只有一個能被執行。例如:
public static void main(String[] args) {try {process1();process2();process3();} catch (IOException e) {System.out.println(e);} catch (NumberFormatException e) {System.out.println(e);}
}
存在多個catch
的時候,catch
的順序非常重要:子類必須寫在前面。例如:
public static void main(String[] args) {try {process1();process2();process3();} catch (IOException e) {System.out.println("IO error");} catch (UnsupportedEncodingException e) { // 永遠捕獲不到System.out.println("Bad encoding");}
}
對于上面的代碼,UnsupportedEncodingException
異常是永遠捕獲不到的,因為它是IOException
的子類。當拋出UnsupportedEncodingException
異常時,會被catch (IOException e) { ... }
捕獲并執行。
因此,正確的寫法是把子類放到前面:
public static void main(String[] args) {try {process1();process2();process3();} catch (UnsupportedEncodingException e) {System.out.println("Bad encoding");} catch (IOException e) {System.out.println("IO error");}
}
finally語句
無論是否有異常發生,如果我們都希望執行一些語句,例如清理工作,怎么寫?
可以把執行語句寫若干遍:正常執行的放到try
中,每個catch
再寫一遍。例如:
public static void main(String[] args) {try {process1();process2();process3();System.out.println("END");} catch (UnsupportedEncodingException e) {System.out.println("Bad encoding");System.out.println("END");} catch (IOException e) {System.out.println("IO error");System.out.println("END");}
}
上述代碼無論是否發生異常,都會執行System.out.println("END");
這條語句。
那么如何消除這些重復的代碼?Java的try ... catch
機制還提供了finally
語句,finally
語句塊保證有無錯誤都會執行。上述代碼可以改寫如下:
public static void main(String[] args) {try {process1();process2();process3();} catch (UnsupportedEncodingException e) {System.out.println("Bad encoding");} catch (IOException e) {System.out.println("IO error");} finally {System.out.println("END");}
}
注意finally
有幾個特點:
finally
語句不是必須的,可寫可不寫;finally
總是最后執行。
如果沒有發生異常,就正常執行try { ... }
語句塊,然后執行finally
。如果發生了異常,就中斷執行try { ... }
語句塊,然后跳轉執行匹配的catch
語句塊,最后執行finally
。
可見,finally
是用來保證一些代碼必須執行的。
某些情況下,可以沒有catch
,只使用try ... finally
結構。例如:
void process(String file) throws IOException {try {...} finally {System.out.println("END");}
}
因為方法聲明了可能拋出的異常,所以可以不寫catch
。
捕獲多種異常
如果某些異常的處理邏輯相同,但是異常本身不存在繼承關系,那么就得編寫多條catch
子句:
public static void main(String[] args) {try {process1();process2();process3();} catch (IOException e) {System.out.println("Bad input");} catch (NumberFormatException e) {System.out.println("Bad input");} catch (Exception e) {System.out.println("Unknown error");}
}
因為處理IOException
和NumberFormatException
的代碼是相同的,所以我們可以把它兩用|
合并到一起:
public static void main(String[] args) {try {process1();process2();process3();} catch (IOException | NumberFormatException e) { // IOException或NumberFormatExceptionSystem.out.println("Bad input");} catch (Exception e) {System.out.println("Unknown error");}
}
練習
用try ... catch
捕獲異常并處理。
下載練習:捕獲異常練習 (推薦使用IDE練習插件快速下載)
小結
使用try ... catch ... finally
時:
- 多個
catch
語句的匹配順序非常重要,子類必須放在前面; finally
語句保證了有無異常都會執行,它是可選的;- 一個
catch
語句也可以匹配多個非繼承關系的異常。 - 關注樂字節,這里有更多更好的Java干貨知識