在程序開發中,異常處理也是咱們常用到的模塊,只是日常不多去深究異常模塊的一些知識點。好比,try-catch 處理要遵循的原則是什麼,finally 爲何老是能執行,try-catch 爲何比較消耗程序的執行性能等問題,咱們本講內容都會給出相應的答案,固然還有面試中常常被問到的異常模塊的一些面試題,也是咱們本篇要講解的重點內容。java
先來看看異常處理的語法格式:面試
try{ ... } catch(Exception e){ ... } finally{ ... }
其中,數據庫
異常處理的基本使用,具體能夠參考下面的代碼段:json
try { int i = 10 / 0; } catch (ArithmeticException e) { System.out.println(e); } finally { System.out.println("finally"); }
多 catch 的使用,具體能夠參考下面的代碼段:數組
try { int i = Integer.parseInt(null); } catch (ArithmeticException ae) { System.out.println("ArithmeticException"); } catch (NullPointerException ne) { System.out.println("NullPointerException"); } catch (Exception e) { System.out.println("Exception"); }
須要注意的是 Java 虛擬機會從上往下匹配錯誤類型,所以前面的 catch 異常類型不能包含後面的異常類型。好比上面的代碼若是把 Exception 放在最前面編譯器就會報錯,具體能夠參考下面的圖片。性能
隨着 Java 語言的發展,JDK 7 的時候引入了一些更加便利的特性,用來更方便的處理異常信息,如 try-with-resources 和 multiple catch,具體能夠參考下面的代碼段:優化
try (FileReader fileReader = new FileReader(""); FileWriter fileWriter = new FileWriter("")) { // try-with-resources System.out.println("try"); } catch (IOException | NullPointerException e) { // multiple catch System.out.println(e); }
先來看下面這段代碼,有沒有發現一些問題?spa
try { // ... int i = Integer.parseInt(null); } catch (Exception e) { }
以上的這段代碼,看似「正常」,卻違背了異常處理的兩個基本原則:線程
異常處理當然好用,但必定不要濫用,好比下面的代碼片斷:指針
// 使用 com.alibaba.fastjson JSONArray array = new JSONArray(); String jsonStr = "{'name':'laowang'}"; try { array = JSONArray.parseArray(jsonStr); } catch (Exception e) { array.add(JSONObject.parse(jsonStr)); } System.out.println(array.size());
這段代碼是藉助了 try-catch 去處理程序的業務邏輯,一般是不可取的,緣由包括下列兩個方面。
以上使用 try-catch 處理業務的代碼,能夠修改成下列代碼:
// 使用 com.alibaba.fastjson JSONArray array = new JSONArray(); String jsonStr = "{'name':'laowang'}"; if (null != jsonStr && !jsonStr.equals("")) { String firstChar = jsonStr.substring(0, 1); if (firstChar.equals("{")) { array.add(JSONObject.parse(jsonStr)); } else if (firstChar.equals("[")) { array = JSONArray.parseArray(jsonStr); } } System.out.println(array.size());
答:try 不能單獨使用,不然就失去了 try 的意義和價值。
try { int i = 10 / 0; } catch { System.out.println("last"); }
答:不能正常運行,catch 後必須包含異常信息,如 catch (Exception e)。
try { int i = 10 / 0; } finally { System.out.println("last"); }
答:能夠正常運行。
try { int i = 10 / 0; System.out.println("try"); } catch (Exception e) { int j = 2 / 0; System.out.println("catch"); } finally { System.out.println("finally"); } System.out.println("main");
答:程序會打印出 finally 以後拋出異常並終止運行。
try { System.out.println("try"); } catch (Exception e) { System.out.println("catch"); } finally { int k = 3 / 0; System.out.println("finally"); } System.out.println("main");
答:程序在輸出 try 以後拋出異常並終止運行,不會再執行 finally 異常以後的代碼。
答:常見的運行時異常以下:
試圖經過字符串來加載某個類時引起的異常;
答:Exception 和 Error 都屬於 Throwable 的子類,在 Java 中只有 Throwable 及其之類才能被捕獲或拋出,它們的區別以下:
答:它們的區別以下:
答:Integer.parseInt(null) 和 Double.parseDouble(null) 拋出的異常類型不同,以下所示:
至於爲何會產生不一樣的異常,其實沒有特殊的緣由,主要是因爲這兩個功能是不一樣人開發的,於是就產生了兩種不一樣的異常信息。
答:這個問題要從 JVM(Java 虛擬機)層面找答案了。首先 Java 虛擬機在構造異常實例的時候須要生成該異常的棧軌跡,這個操做會逐一訪問當前線程的棧幀,而且記錄下各類調試信息,包括棧幀所指向方法的名字,方法所在的類名、文件名,以及在代碼中的第幾行觸發該異常等信息,這就是使用異常捕獲耗時的主要緣由了。
答:常見的 OOM 緣由有如下幾個:
public static int getNumber() { try { int number = 0 / 1; return 2; } finally { return 3; } }
A:0
B:2
C:3
D:1
答:3
題目解析:程序最後必定會執行 finally 裏的代碼,會把以前的結果覆蓋爲 3。
答:finally、finalize 的區別以下:
答:finally 總會被執行,都是編譯器的做用,由於編譯器在編譯 Java 代碼時,會複製 finally 代碼塊的內容,而後分別放在 try-catch 代碼塊全部的正常執行路徑及異常執行路徑的出口中,這樣 finally 纔會無論發生什麼狀況都會執行。
歡迎關注個人公衆號,回覆關鍵字「Java」 ,將會有大禮相送!!! 祝各位面試成功!!!