精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

詳解Java中重要的錯誤處理機制異常

開發 后端
異常作為Java語言中重要的錯誤處理機制,也作為查找程序原因,提升程序健壯性,前端產品良好體驗的重要保障,所以掌握異常的使用是非常有必要的,希望本文能對大家有所幫助,如果有什么疑問或問題歡迎隨時騷擾。

[[384494]]

 本文轉載自微信公眾號「我是開發者FTD」,作者FTD。轉載本文請聯系我是開發者FTD公眾號。

hi,大家好,我是開發者FTD。今天我們來聊一聊Java語言中的異常處理機制。

Java 語言誕生于1995年,距現在已經有26年的時間了。作為一門比較老的語言依然擁有強大的生命力,Java在很多方面(例如高并發,移植性等)具有明顯的優勢,當然在一些方面(例如圖像處理)也有不足,今天要給大家介紹的異常就是Java語言中提供的一個強大的,可以讓我們正確合理的應對程序中發生錯誤的機制。

一、異常介紹

什么是異常?

異常是指程序在運行過程中發生的,由于外部問題導致的程序運行異常事件,異常的發生往往會中斷程序的運行。在 Java 這種面向對象的編程語言中,萬物都是對象,異常本身也是一個對象,程序發生異常就會產生一個異常對象。

異常的分類

講到異常的分類,就不能不說一下Java異常的繼承結構。如下圖所示:

Throwable

從圖中可以看到,異常主要有以下類構成:

  • Throwable
  • Error
  • Exception

接下來我們就分別介紹一下這幾個基類的作用。

Throwable

Throwable 類是 Java 語言中所有錯誤或異常的頂層父類,其他異常類都繼承于該類。Throwable類有兩個重要的子類:**Exception(異常)**和 「Error(錯誤)」,二者都是 Java 異常處理的重要子類,各自都包含大量子類。

只有當對象是此類或其子類的實例時,才能通過 Java 虛擬機或者 Java throw 語句拋出。類似地,只有此類或其子類才可以是 catch 子句中的參數類型。

Throwable 對象中包含了其線程創建時線程執行堆棧的快照,它還包含了給出有關錯誤更多信息的消息字符串。

最后,它還可以包含 cause(原因):另一個導致此 throwable 拋出的 throwable。此 cause 設施在 1.4 版本中首次出現。它也稱為異常鏈設施,因為 cause 自身也會有 cause,依此類推,就形成了異常鏈,每個異常都是由另一個異常引起的。

Error

Error 是 Throwable 的子類,通常情況下應用程序「不應該試圖捕獲的嚴重問題」。

Error 是程序無法處理的錯誤,表示運行應用程序中較嚴重問題。大多數錯誤與代碼編寫者執行的操作無關,而表示代碼運行時 JVM(Java 虛擬機)出現的問題。

例如:Java虛擬機運行錯誤(Virtual MachineError),當 JVM 不再有繼續執行操作所需的內存資源時,將出現 OutOfMemoryError。這些異常發生時,Java虛擬機(JVM)一般會選擇線程終止。

這些錯誤表示故障發生于虛擬機自身、或者發生在虛擬機試圖執行應用時,如Java虛擬機運行錯誤(Virtual MachineError)、類定義錯誤(NoClassDefFoundError)等。這些錯誤是不可查的,因為它們在應用程序的控制和處理能力之 外,而且絕大多數是程序運行時不允許出現的狀況。對于設計合理的應用程序來說,即使確實發生了錯誤,本質上也不應該試圖去處理它所引起的異常狀況。在 Java中,錯誤通過Error的子類描述。

Exception

Exception以及它的子類,代表程序運行時發送的各種不期望發生的事件??梢员籎ava異常處理機制使用,是異常處理的核心。

Exception 異常主要分為兩類:

「1、非檢查性異常(unchecked exception)」

Error 和 RuntimeException 以及他們的子類。Java語言在編譯時,不會提示和發現這樣的異常,不要求在程序中處理這些異常。所以我們可以在程序中編寫代碼來處理(使用try…catch…finally)這樣的異常,也可以不做任何處理。對于這些錯誤或異常,我們應該修正代碼,而不是去通過異常處理器處理。這樣的異常發生的原因多半是由于我們的代碼邏輯出現了問題。

例如:

  • 當程序中用數字除以0時,就會拋出ArithmeticException異常;
  • 在類型轉換時,錯誤的強制類型轉換會拋出ClassCastException類型轉換異常;
  • 當使用集合進行數組索引越界時就會拋出ArrayIndexOutOfBoundsException異常;
  • 當程序中使用了空對象進行操作時就會拋出注明的空指針NullPointerException異常等。

「常見的非檢查性異常有」:

異常 描述
ArithmeticException 當出現異常的運算條件時,拋出異常。例如,一個整數“除以零”時,拋出此類的一個實例。
ArrayIndexOutOfBoundsException 用非法索引訪問數組時跑出的異常。如果索引為負或大于等于數組大小,則該索引為非法索引。
ArrayStoreException 試圖將錯誤類型的對象存儲到一個對象數組時,拋出的異常。
ClassCastException 試圖將對象強制轉換為不是同一個類型或其子類的實例時,拋出的異常。
IllegalArgumentException 當向一個方法傳遞非法或不正確的參數時,拋出該異常。
IllegalMonitorStateException 當某一線程已經試圖等待對象的監視器,或者通知其他正在等待該對象監視器的線程,而該線程本身沒有獲得指定監視器時拋出該異常。
IllegalStateException 在非法或不適當的時間調用方法時產生的信號。或者說Java環境或應用程序沒有處于請求操作所要求的適當狀態下。
IllegalThreadStateException 線程沒有處于請求操作所要求的適當狀態時,拋出該異常。
IndexOutOfBoundsException 當某種排序的索引超出范圍時拋出的異常,例如,一個數組,字符串或一個向量的排序等。
NegativeArraySizeException 如果應用程序試圖創建大小為負的數組時,拋出該異常。
NullPointerException 當應用程序在需要操作對象的時候而獲得的對象實例是null時拋出該異常。
NumberFormatException 當應用程序試圖將字符串轉換成一種數值類型,但該字符串不能轉換為適當格式時,拋出該異常。
SecurityException 由安全管理器拋出的異常,指示存在安全侵犯。
StringIndexOutOfBoundsException 此異常由String方法拋出,說明索引為負或者超出了字符串的大小。

「2、檢查性異常(checked exception)」

除了Error 和 RuntimeException的其它異常。Java語言強制要求程序員為這樣的異常做預備處理工作(使用try…catch…finally或者throws)。在方法中要么用try-catch語句捕獲它并處理,要么用throws子句聲明拋出它,否則編譯不會通過。這樣的異常一般是由程序的運行環境導致的。因為程序可能被運行在各種未知的環境下,而程序員無法干預用戶如何使用他編寫的程序,于是程序員就應該為這樣的異常時刻準備著。如SQLException,IOException,ClassNotFoundException 等。

檢查性異常就是指,編譯器在編譯期間要求必須得到處理的那些異常,你必須在編譯期處理了。

「常見的檢查性異常有」:

異常 描述
ClassNotFoundException 當應用程序試圖加載一個類,通過名字查找時卻發現沒有該類的定義時,拋出該異常。
CloneNotSupportedException 當去克隆一個對象時,發現該對象沒有實現Cloneable接口時,拋出該異常。
IllegalAccessException 當應用程序嘗試通過反射的方式來訪問類、成員變量或調用方法時,卻無法訪問這些類、成員變量或方法的定義時,拋出該異常。
InstantiationException 當試圖使用Class類中的newInstance方法創建一個類的實例,而制定的類對象因為是一個接口或是一個抽象類而無法實例化時,拋出該異常。
InterruptedException 一個線程被另一個線程中斷時,拋出該異常。
NoSuchFieldException 當找不到指定的變量字段時,拋出該異常、
NoSuchMethodException 當找不到指定的類方法時,拋出該異常。

二、初識異常

下面我們通過一個簡單實例,讓大家更直觀的認識一下Java的異常。

下面的代碼會拋出著名的空指針異常:NullPointerException。

  1. public class Test { 
  2.     private int a = 1; 
  3.     private int b = 2; 
  4.  
  5.     public static void main(String[] args) { 
  6.         Test t1 = new Test(); 
  7.         Test t2 = null
  8.         System.out.println(t1.a); 
  9.         System.out.println(t2.a); 
  10.         System.out.println(t2.c()); 
  11.     } 
  12.  
  13.     public String c() { 
  14.         return "微信公眾號:我是開發者FTD"
  15.     } 

運行程序,控制臺輸出結果如下:

  1. Exception in thread "main" java.lang.NullPointerException 
  2.  at cc.devclub.ftd.Test.main(Test.java:11) 
  3.  
  4. Process finished with exit code 1 

從控制臺輸出可以看到,程序打印了 “1”,然后在程序的第11行的位置拋出了 「java.lang.NullPointerException」 ,然后程序就終止運行了。

三、異常處理機制

在編寫代碼處理異常時,對于檢查性異常,有兩種不同的處理方式:

  • 使用 「try…catch…finally…」 語句塊處理
  • 在方法中使用 「throws/throw」 關鍵詞將異常交給方法調用者去處理

try...catch...finally… 關鍵字

  • 使用 try 和 catch 關鍵字可以捕獲異常。
  • try/catch 代碼塊放在異常可能發生的地方。

try/catch代碼塊中的代碼稱為保護代碼,使用 try/catch 的語法如下:

  1. try { 
  2.     ... 
  3. } catch (IOException ioException) { 
  4.     ... 
  5. } catch (Exception exception) { 
  6.     ... 
  7. } finally { 
  8.     ... 

「try 塊:」

  • try塊中放可能發生異常的代碼。
  • 如果執行完try且不發生異常,則接著去執行finally塊中的代碼和finally后面的代碼(如果有的話)。
  • 如果程序發生異常,則嘗試去匹配對應的catch塊。

「catch 塊:」

  • 每一個catch塊用于捕獲并處理一個特定的異常,或者這異常類型的子類。Java7中可以將多個異常聲明在一個catch中。
  • catch后面的括號定義了異常類型和異常參數。如果異常與之匹配且是最先匹配到的,則虛擬機將使用這個catch塊來處理異常。
  • 在catch塊中可以使用這個塊的異常參數來獲取異常的相關信息。異常參數是這個catch塊中的局部變量,其它塊不能訪問。
  • 如果當前try塊中發生的異常在后續的所有catch中都沒捕獲到,則先去執行finally,然后到這個方法的外部調用者中去匹配異常處理器。
  • 如果try中沒有發生異常,則所有的catch塊將被忽略。

「需要注意的地方」

1、try塊中的局部變量和catch塊中的局部變量(包括異常變量),以及finally中的局部變量,他們之間不可共享使用。

2、每一個catch塊用于處理一個異常。異常匹配是按照catch塊的順序從上往下尋找的,只有第一個匹配的catch會得到執行。匹配時,不僅運行精確匹配,也支持父類匹配,因此,如果同一個try塊下的多個catch異常類型有父子關系,應該將子類異常放在前面,父類異常放在后面,這樣保證每個catch塊都有存在的意義。

3、Java中,異常處理的任務就是將執行控制流從異常發生的地方轉移到能夠處理這種異常的地方去。也就是說:當一個方法的某條語句發生異常時,這條語句的后面的語句不會再執行,它失去了焦點。執行流跳轉到最近的匹配的異常處理catch代碼塊去執行,異常被處理完后,執行流會接著在“處理了這個異常的catch代碼塊”后面接著執行。

「finally 塊:」

  • finally塊不是必須的,通常是可選的。
  • 無論異常是否發生,異常是否匹配被處理,finally中的代碼都會執行。
  • 一個try至少要有一個catch塊,否則, 至少要有1個finally塊。但是finally不是用來處理異常的,finally不會捕獲和處理異常,處理異常的只能是catch塊。
  • finally主要做一些清理工作,如流的關閉,數據庫連接的關閉等。
  • finally塊不管異常是否發生,只要對應的try執行了,則它一定也執行。只有一種方法讓finally塊不執行:「System.exit()」 。

大家需要養成**良好的編程習慣是:**在try塊中打開資源,在finally塊中清理并釋放這些資源,以免造成內存泄露。

「需要注意的地方:」

1、在同一try…catch…finally…塊中,如果try中拋出異常,且有匹配的catch塊,則先執行catch塊,再執行finally塊。如果沒有catch塊匹配,則先執行finally,然后去到上層的調用者中尋找合適的catch塊。

2、在同一try…catch…finally…塊中 ,try發生異常,且匹配的catch塊中處理異常時也拋出異常,那么后面的finally也會執行:首先執行finally塊,然后去上層調用者中尋找合適的catch塊。

throws/throw 關鍵字

  • 「throws 關鍵字」

如果一個方法內部的代碼會拋出檢查性異常(checked exception),而方法自己又沒有對這些異常完全處理掉,則java的編譯器會要求你必須在方法的簽名上使用 「throws」 關鍵字聲明這些可能拋出的異常,否則編譯不通過。

throws 是另一種處理異常的方式,它不同于try…catch…finally…,throws 關鍵字僅僅是將方法中可能出現的異常向調用者拋出,而自己則不具體處理。

采取這種異常處理的原因可能是:方法本身不知道如何處理這樣的異常,或者說讓調用者處理更好,調用者需要為可能發生的異常負責。

  • 「throw 關鍵字」

我們也可以通過 throw 語句手動顯式的拋出一個異常,throw語句的后面必須是一個異常對象。語法如下:

throw exceptionObject

throw 語句必須寫在方法中,執行throw 語句的地方就是一個異常拋出點,它和由JRE自動形成的異常拋出點沒有任何差別。

  1. public void save(User user) { 
  2.     if (user == null
  3.         throw new IllegalArgumentException("User對象為空"); 
  4.     //...... 

try-catch-finally 的執行順序

try-catch-finally 執行順序的相關問題可以說是各種面試中的「??汀沽耍绕涫?finally 塊中帶有 return 語句的情況。我們直接看幾道面試題:

「面試題一:」

  1. public static void main(String[] args) { 
  2.     int result = test1(); 
  3.     System.out.println(result); 
  4.  
  5. public static int test1() { 
  6.     int i = 1; 
  7.     try { 
  8.         i++; 
  9.         System.out.println("try block, i = " + i); 
  10.     } catch (Exception e) { 
  11.         i--; 
  12.         System.out.println("catch block i = " + i); 
  13.     } finally { 
  14.         i = 10; 
  15.         System.out.println("finally block i = " + i); 
  16.     } 
  17.     return i; 

大家不妨算一算程序員最終運行的結果是什么。

輸出結果如下:

  1. try block, i = 2 
  2. finally block i = 10 
  3. 10 

這算一個相當簡單的問題了,沒有坑,下面我們稍微改動一下:

  1. public static int test2() { 
  2.     int i = 1; 
  3.     try { 
  4.         i++; 
  5.         throw new Exception(); 
  6.     } catch (Exception e) { 
  7.         i--; 
  8.         System.out.println("catch block i = " + i); 
  9.     } finally { 
  10.         i = 10; 
  11.         System.out.println("finally block i = " + i); 
  12.     } 
  13.     return i; 

輸出結果如下:

  1. catch block i = 1 
  2. finally block i = 10 
  3. 10 

運行結果想必也是意料之中吧,程序拋出一個異常,然后被本方法的 catch 塊捕獲并進行了處理。

「面試題二:」

  1. public static void main(String[] args) { 
  2.     int result = test3(); 
  3.     System.out.println(result); 
  4.  
  5. public static int test3() { 
  6.     //try 語句塊中有 return 語句時的整體執行順序 
  7.     int i = 1; 
  8.     try { 
  9.         i++; 
  10.         System.out.println("try block, i = " + i); 
  11.         return i; 
  12.     } catch (Exception e) { 
  13.         i++; 
  14.         System.out.println("catch block i = " + i); 
  15.         return i; 
  16.     } finally { 
  17.         i = 10; 
  18.         System.out.println("finally block i = " + i); 
  19.     } 

輸出結果如下:

  1. try block, i = 2 
  2. finally block i = 10 

是不是有點疑惑?明明我 try 語句塊中有 return 語句,可為什么最終還是執行了 finally 塊中的代碼?

我們反編譯這個類,看看這個 test3 方法編譯后的字節碼的實現:

  1. 0: iconst_1         //將 1 加載進操作數棧 
  2. 1: istore_0         //將操作數棧 0 位置的元素存進局部變量表 
  3. 2: iinc          0, 1   //將局部變量表 0 位置的元素直接加一(i=2) 
  4. 5: getstatic     #3     // 5-27 行執行的 println 方法                 
  5. 8: new           #5                   
  6. 11: dup 
  7. 12: invokespecial #6                                                      
  8. 15: ldc           #7  
  9. 17: invokevirtual #8                                                      
  10. 20: iload_0          
  11. 21: invokevirtual #9                                                      
  12. 24: invokevirtual #10                 
  13. 27: invokevirtual #11                  
  14. 30: iload_0         //將局部變量表 0 位置的元素加載進操作棧(2) 
  15. 31: istore_1        //把操作棧頂的元素存入局部變量表位置 1 處 
  16. 32: bipush        10 //加載一個常量到操作棧(10) 
  17. 34: istore_0        //將 10 存入局部變量表 0 處 
  18. 35: getstatic     #3  //35-57 行執行 finally中的println方法              
  19. 38: new           #5                   
  20. 41: dup 
  21. 42: invokespecial #6                   
  22. 45: ldc           #12                  
  23. 47: invokevirtual #8                   
  24. 50: iload_0 
  25. 51: invokevirtual #9                 
  26. 54: invokevirtual #10                  
  27. 57: invokevirtual #11                  
  28. 60: iload_1         //將局部變量表 1 位置的元素加載進操作棧(2) 
  29. 61: ireturn         //將操作棧頂元素返回(2) 
  30. -------------------try + finally 結束 ------------ 
  31. ------------------下面是 catch + finally,類似的 ------------ 
  32. 62: astore_1 
  33. 63: iinc          0, 1 
  34. ....... 
  35. ....... 

從我們的分析中可以看出來,finally 代碼塊中的內容始終會被執行,無論程序是否出現異常的原因就是,「編譯器會將 finally 塊中的代碼復制兩份并分別添加在 try 和 catch 的后面」。

可能有人會所疑惑,原本我們的 i 就被存儲在局部變量表 0 位置,而最后 finally 中的代碼也的確將 slot 0 位置填充了數值 10,可為什么最后程序依然返回的數值 2 呢?

仔細看字節碼,你會發現在 return 語句返回之前,虛擬機會將待返回的值壓入操作數棧,等待返回,即使 finally 語句塊對 i 進行了修改,但是待返回的值已經確實的存在于操作數棧中了,所以不會影響程序返回結果。

「面試題三:」

  1. public static int test4() { 
  2.     //finally 語句塊中有 return 語句 
  3.     int i = 1; 
  4.     try { 
  5.         i++; 
  6.         System.out.println("try block, i = " + i); 
  7.         return i; 
  8.     } catch (Exception e) { 
  9.         i++; 
  10.         System.out.println("catch block i = " + i); 
  11.         return i; 
  12.     } finally { 
  13.         i++; 
  14.         System.out.println("finally block i = " + i); 
  15.         return i; 
  16.     } 

運行結果:

  1. try block, i = 2 
  2. finally block i = 3 

其實你從它的字節碼指令去看整個過程,而不要單單死記它的執行過程。

你會發現程序最終會采用 finally 代碼塊中的 return 語句進行返回,而直接忽略 try 語句塊中的 return 指令。

自定義異常

Java 的異常機制中所定義的所有異常不可能預見所有可能出現的錯誤,某些特定的情境下,則需要我們自定義異常類型來向上報告某些錯誤信息。

而自定義異常類型也是相當簡單的,你可以選擇繼承 Throwable,Exception 或它們的子類,甚至你不需要實現和重寫父類的任何方法即可完成一個異常類型的定義。

例如:

  1. public class MyException extends RuntimeException{ }  
  2. public class MyException extends Exception{ } 

按照國際慣例,自定義的異常應該總是包含如下的構造函數:

  • 一個無參構造函數
  • 一個帶有String參數的構造函數,并傳遞給父類的構造函數。
  • 一個帶有String參數和Throwable參數,并都傳遞給父類構造函數
  • 一個帶有Throwable 參數的構造函數,并傳遞給父類的構造函數。

下面是IOException類的完整源代碼,我們可以參考:

  1. public class IOException extends Exception { 
  2.     static final long serialVersionUID = 7818375828146090155L; 
  3.  
  4.     public IOException() { 
  5.         super(); 
  6.     } 
  7.  
  8.     public IOException(String message) { 
  9.         super(message); 
  10.     } 
  11.  
  12.     public IOException(String message, Throwable cause) { 
  13.         super(message, cause); 
  14.     } 
  15.  
  16.     public IOException(Throwable cause) { 
  17.         super(cause); 
  18.     } 

異常的注意事項

1、當子類重寫父類的帶有 throws聲明的函數時,其throws聲明的異常必須在父類異常的可控范圍內——用于處理父類的throws方法的異常處理器,必須也適用于子類的這個帶throws方法 。這是為了支持多態。

例如,父類方法throws 的是2個異常,子類就不能throws 3個及以上的異常。父類throws IOException,子類就必須throws IOException或者IOException的子類。

2、Java程序可以是多線程的。每一個線程都是一個獨立的執行流,獨立的函數調用棧。如果程序只有一個線程,那么沒有被任何代碼處理的異常 會導致程序終止。如果是多線程的,那么沒有被任何代碼處理的異常僅僅會導致異常所在的線程結束。

也就是說,Java中的異常是線程獨立的,線程的問題應該由線程自己來解決,而不要委托到外部,也不會直接影響到其它線程的執行。

異常使用時的常見錯誤

1、將異常直接顯示在頁面或客戶端

將異常直接打印在客戶端的例子屢見不鮮,一旦程序運行出現異常,默認情況下容器將異常堆棧信息直接打印在頁面上。從客戶角度來說,任何異常都沒有實際意義,絕大多數的客戶也根本看不懂異常信息,軟件開發也要盡量避免將異常直接呈現給用戶,一定要在前端展示層對異常進行封裝后展示。目前絕大多數應用都是前后端分離的模式,這種直接打印異常的情況已經相對改善了很多,不過我們在編碼時還是要特別注意下這個原則。

2、忽略異常

如下異常處理只是將異常輸出到控制臺,沒有任何意義。而且這里出現了異常并沒有中斷程序,進而調用代碼繼續執行,導致更多的異常。

  1. public void retrieveObjectById(Long id) { 
  2.     try { 
  3.         //..some code that throws SQLException 
  4.     } catch (SQLException ex) { 
  5.         /** 
  6.           *了解的人都知道,這里的異常打印毫無意義,僅僅是將錯誤堆棧輸出到控制臺。 
  7.           * 而在 Production 環境中,需要將錯誤堆棧輸出到日志。 
  8.           * 而且這里 catch 處理之后程序繼續執行,會導致進一步的問題*/ 
  9.  
  10.         ex.printStacktrace(); 
  11.     } 

捕獲了異常缺不進行處理,這是我們在寫代碼時候的大忌,可以重構成:

  1. public void retrieveObjectById(Long id) { 
  2.     try { 
  3.         //..some code that throws SQLException 
  4.     } catch (SQLException ex) { 
  5.         throw new RuntimeException("Exception in retieveObjectById”, ex); 
  6.     } finally { 
  7.         //clean up resultset, statement, connection etc 
  8.     } 

3、將異常包含在循環語句塊中

如下代碼所示,異常包含在 for 循環語句塊中。

  1. for (int i = 0; i < 100; i++) { 
  2.     try { 
  3.     } catch (XXXException e) { 
  4.         //.... 
  5.     } 

我們都知道異常處理占用系統資源。一看,大家都認為不會犯這樣的錯誤。換個角度,類 A 中執行了一段循環,循環中調用了 B 類的方法,B 類中被調用的方法卻又包含 try-catch 這樣的語句塊。褪去類的層次結構,代碼和上面如出一轍。

4、利用 Exception 捕捉所有潛在的異常

一段方法執行過程中拋出了幾個不同類型的異常,為了代碼簡潔,利用基類 Exception 捕捉所有潛在的異常,如下例所示:

  1. public void retrieveObjectById(Long id) { 
  2.     try { 
  3.         //...拋出 IOException 的代碼調用 
  4.         //...拋出 SQLException 的代碼調用 
  5.     } catch (Exception e) { 
  6.         //這里利用基類 Exception 捕捉的所有潛在的異常,如果多個層次這樣捕捉,會丟失原始異常的有效信息 
  7.         throw new RuntimeException("Exception in retieveObjectById”, e); 
  8.     } 

估計大部分程序員都會有這種寫法,為了省事簡便,直接一個頂層的exception來捕獲所有可能出現的異常,這樣雖然可以保證異常肯定會被捕捉到,但是程序卻無法針對不同的錯誤異常進行對應正確的處理,可以重構成:

  1. public void retrieveObjectById(Long id) { 
  2.     try { 
  3.         //..some code that throws RuntimeException, IOException, SQLException 
  4.     } catch (IOException e) { 
  5.         //僅僅捕捉 IOException 
  6.         throw new RuntimeException(/*指定這里 IOException 對應的錯誤代碼*/code, "Exception in retieveObjectById”, e); 
  7.     } catch (SQLException e) { 
  8.         //僅僅捕捉 SQLException 
  9.         throw new RuntimeException(/*指定這里 SQLException 對應的錯誤代碼*/code, "Exception in retieveObjectById”, e); 
  10.     } 

5、異常包含的信息不能充分定位問題

異常不僅要能夠讓開發人員知道哪里出了問題,更多時候開發人員還需要知道是什么原因導致的問題,我們知道 java .lang.Exception 有字符串類型參數的構造方法,這個字符串可以自定義成通俗易懂的提示信息。

簡單的自定義信息開發人員只能知道哪里出現了異常,但是很多的情況下,開發人員更需要知道是什么參數導致了這樣的異常。這個時候我們就需要將方法調用的參數信息追加到自定義信息中。下例只列舉了一個參數的情況,多個參數的情況下,可以單獨寫一個工具類組織這樣的字符串。

  1. public void retieveObjectById(Long id) { 
  2.     try { 
  3.         //..some code that throws SQLException 
  4.     } catch (SQLException ex) { 
  5.         //將參數信息添加到異常信息中 
  6.         throw new RuntimeException("Exception in retieveObjectById with Object Id :"+ id, ex); 
  7.     } 

總結

異常作為Java語言中重要的錯誤處理機制,也作為查找程序原因,提升程序健壯性,前端產品良好體驗的重要保障,所以掌握異常的使用是非常有必要的,希望本文能對大家有所幫助,如果有什么疑問或問題歡迎隨時騷擾。

 

責任編輯:武曉燕 來源: 我是開發者FTD
相關推薦

2011-03-17 09:20:05

異常處理機制

2009-06-19 16:20:14

ASP.NET錯誤處理

2009-07-31 11:28:42

錯誤處理機制ASP.NET

2010-03-05 15:40:16

Python異常

2011-04-06 10:27:46

Java異常處理

2011-07-21 15:20:41

java異常處理機制

2025-07-07 03:00:00

異常處理Result模式

2017-05-10 21:28:00

Java異常與錯誤處理

2024-03-27 08:18:02

Spring映射HTML

2023-06-15 14:09:00

解析器Servlet容器

2021-07-03 17:53:52

Java異常處理機制

2015-10-09 13:54:14

切面編程錯誤處理機制

2024-03-04 10:00:35

數據庫處理機制

2023-02-23 08:15:33

Spring異常處理機制

2015-12-28 11:25:51

C++異常處理機制

2025-02-10 09:49:00

2009-08-05 18:09:17

C#異常處理機制

2023-03-08 08:54:59

SpringMVCJava

2009-09-02 18:34:28

C#鼠標事件

2024-09-24 17:34:05

點贊
收藏

51CTO技術棧公眾號

日本一级淫片免费放| 免费看成人片| 久久久久97国产| 国内精品免费| 91久久人澡人人添人人爽欧美| 欧美午夜精品久久久久久蜜| 亚洲一卡二卡在线观看| 国产精品豆花视频| 在线亚洲男人天堂| 日本国产在线视频| 国产精品久久久久久久久免费高清 | 欧美性生活大片免费观看网址| 天堂资源在线亚洲视频| 蜜臀av午夜精品| 麻豆精品一区二区三区| 国内精久久久久久久久久人| 男女全黄做爰文章| 奇米777国产一区国产二区| 欧美日韩一区三区四区| 日韩精品免费一区| 91大神xh98hx在线播放| 成人午夜碰碰视频| 成人免费午夜电影| 天堂免费在线视频| 亚洲视频成人| 欧美国产亚洲视频| 欧美手机在线观看| 成人影视亚洲图片在线| 日韩电影中文字幕在线| 欧美高清精品一区二区| 成人久久网站| 在线观看欧美精品| 黄色免费视频大全| 深夜国产在线播放| 中文字幕一区二区三区av| 免费看国产精品一二区视频| 高h调教冰块play男男双性文| 日本不卡视频一二三区| 青青草精品毛片| 亚洲一区欧美在线| 亚洲性视频h| 欧美巨乳美女视频| 国产少妇在线观看| 久久精品亚洲人成影院| 综合久久五月天| mm131丰满少妇人体欣赏图| 欧美电影在线观看免费| 亚洲国产97在线精品一区| 一个人看的视频www| 伊人国产精品| 在线成人av网站| 久国产精品视频| 青青国产精品| 91精品在线免费| www.午夜av| 日韩08精品| 日韩精品一区二区在线观看| 国产精品99精品无码视亚| 久久三级中文| 日韩女同互慰一区二区| 制服丝袜中文字幕第一页| 一区二区三区无毛| 欧美tickling网站挠脚心| 麻豆av免费看| 美国十次av导航亚洲入口| 亚洲国产精品悠悠久久琪琪 | 激情小说亚洲色图| 亚洲精品99999| 在线免费观看日韩av| 亚洲亚洲免费| 色悠悠久久久久| 黄色一级视频免费| 99在线热播精品免费99热| 4438全国成人免费| 国产又粗又猛又爽又| 裸体一区二区三区| 91超碰在线免费观看| 日本美女一级视频| 国产网站一区二区三区| 亚洲一区bb| 大桥未久在线播放| 日韩欧美在线播放| 人人爽人人爽av| 亚洲中文字幕久久精品无码喷水| av男人天堂av| av中文一区二区三区| 日韩一区二区三区资源| a篇片在线观看网站| 亚洲国产wwwccc36天堂| 午夜dv内射一区二区| 亚洲视频资源| 日韩福利视频在线观看| 日本成人精品视频| 日韩一级免费| 国产精品乱码妇女bbbb| 大胆欧美人体视频| 日韩成人在线免费视频| 日韩国产精品91| a级片免费在线观看| 国产精品丝袜一区| 国产午夜精品视频一区二区三区| 免费看男女www网站入口在线| 在线观看成人小视频| 国产乱码一区二区三区四区| 欧美亚洲大陆| 久色乳综合思思在线视频| 天天综合网入口| 国产一区二区三区久久久| 精品无人区一区二区三区 | 成人av网站免费观看| 日韩偷拍一区二区| 高清电影在线观看免费| 欧美日韩一区二区在线观看| 国产高潮视频在线观看| 日韩精品看片| 国产999精品视频| 亚洲女人18毛片水真多| 国产精品久久久久久一区二区三区| av免费看网址| 欧美一级片网址| 在线观看精品自拍私拍| 国产精品丝袜久久久久久消防器材| 国产成人精品一区二三区四区五区| av亚洲精华国产精华精| 青青草免费在线视频观看| 国产精品嫩草69影院| 精品不卡一区| 欧美在线激情网| 亚洲爆乳无码一区二区三区| 国产精品久久久久aaaa樱花 | 久久久久久黄| 国产综合欧美在线看| 天堂8中文在线| 91麻豆精品国产自产在线| 老头老太做爰xxx视频| 国产亚洲亚洲| 久久99国产精品99久久| segui88久久综合| 精品乱人伦小说| 精国产品一区二区三区a片| 国产一区二区福利视频| 大桥未久一区二区三区| 高清亚洲高清| 色先锋资源久久综合5566| 在线观看你懂的网站| 国产校园另类小说区| 黄色国产精品视频| 午夜精品影视国产一区在线麻豆| 欧美一级在线播放| 日本中文字幕电影在线观看 | 欧美日韩国产999| 精品国产伦一区二区三区| 亚洲素人一区二区| 久久久久亚洲av片无码v| 亚洲精品二区三区| 亚洲最大av网站| 色www永久免费视频首页在线| 日韩久久久精品| av免费看网址| 91丨九色丨丰满| 国产精品成人免费精品自在线观看 | 国内精品久久久久久久影视简单| www高清在线视频日韩欧美| 中文字幕网址在线| 国产精品电影院| 欧洲美女亚洲激情| 国内精品美女在线观看| 国产富婆一区二区三区 | 国产成人一区二区三区小说| 国产香蕉视频在线看| 欧美日韩精品一区视频| 天堂а√在线中文在线鲁大师| 国产一区在线看| 亚洲国产精品无码av| 四虎影视精品| 国产精品香蕉在线观看| 国产乱子轮精品视频| 91久久久久久久久久久久久| 99在线视频观看| 亚洲国产成人在线播放| 中文字幕免费高清网站| 久久久久久久久久久久久久久| 姬川优奈av一区二区在线电影| 欧美日韩国产传媒| 日韩欧美国产wwwww| 麻豆chinese极品少妇| 波多野洁衣一区| 老熟妇仑乱视频一区二区| 久久精品久久综合| 91精品视频免费观看| 直接在线观看的三级网址| 欧美成人video| 特级毛片www| 国产精品久99| 亚洲天堂av网站| 国产精品区一区二区三含羞草| 色wwwwww| 欧美性猛交xxxx富婆弯腰| 懂色av蜜桃av| 国产成人精品亚洲777人妖| 18岁网站在线观看| 亚洲精品网址| 日本精品二区| 亚洲专区**| 国产精品一区二区三区久久久| 动漫一区二区| 俺去亚洲欧洲欧美日韩| 国产又爽又黄网站亚洲视频123| 欧美日韩不卡视频| 亚洲免费激情视频| 国产精品久久看| 女~淫辱の触手3d动漫| 国产精品一区二区无线| 草草草在线视频| 在线观看日韩av电影| 亚洲一区高清| 免费欧美激情| 国产女主播一区二区| **精品中文字幕一区二区三区| 欧美亚洲激情在线| 制服丝袜在线播放| 日韩中文字幕国产精品| 免费毛片在线| 亚洲国产成人在线视频| 亚洲精品久久久蜜桃动漫| 欧美精选午夜久久久乱码6080| 亚洲欧美偷拍视频| 亚洲午夜av在线| 欧美精品99久久久| 精品一区二区在线看| 国产人成一区二区三区影院| 成年人视频在线免费| 亚洲午夜黄色| 日本福利视频网站| 综合久久综合| 久久最新免费视频| 91精品一区二区三区综合在线爱| 男人天堂综合| 久久综合成人精品亚洲另类欧美 | 精品av久久久久电影| 亚洲黄色一区二区三区| 亚洲午夜久久| 日本视频一区二区不卡| 国产精品欧美日韩一区| 日韩第一页在线| 性生活三级视频| 日韩一级成人av| h片在线免费看| 欧美一区二区三区思思人| 国产又粗又大又爽视频| 欧美精选一区二区| aaa国产视频| 欧美成人一区二区三区| 亚洲精华国产精华精华液网站| 欧美成人a∨高清免费观看| www.久久成人| 日韩大陆欧美高清视频区| 偷拍自拍在线| 亚洲色图50p| √天堂资源地址在线官网| 色偷偷亚洲男人天堂| 黄在线免费看| 欧美精品激情在线观看| 欧美13videosex性极品| 国产精品27p| 宅男噜噜噜66国产精品免费| 成人午夜电影免费在线观看| 免费萌白酱国产一区二区三区| 欧美成人dvd在线视频| 精品美女久久久| 最新欧美日韩亚洲| 激情自拍一区| 超碰在线公开97| 国产盗摄女厕一区二区三区 | 国产三区在线播放| 日韩精品一区二区三区四区| 日本福利片在线| 95精品视频| 欧美日韩成人免费| 五月天av在线| 91色精品视频在线| 日本国产精品| 五月天色婷婷综合| 亚洲麻豆av| 国产又黄又猛的视频| 成人网在线播放| 91成人国产| 国精产品一区二区| 精品国产一区二区三区四区| av不卡在线免费观看| 日韩视频久久| 日本一二区免费| 99国产麻豆精品| 永久免费看mv网站入口| 午夜精品一区二区三区免费视频| 亚洲精品国产精品乱码视色| 欧美一级生活片| 久久电影中文字幕| 亚洲免费伊人电影| 国产三级国产精品国产国在线观看| 亚州成人在线电影| 一级片免费网站| 亚洲精品自在久久| 欧洲在线视频| 91精品久久久久久久| 西瓜成人精品人成网站| 中文字幕在线中文| 男女性色大片免费观看一区二区| 国产成人av在线| 69堂精品视频在线播放| 国产精品免费一区二区| 91欧美在线| 能在线观看的av网站| 成人黄色网址在线观看| 成年人免费视频播放| 欧美性猛交xxxx偷拍洗澡| 99久久精品国产色欲| 上原亚衣av一区二区三区| 日韩欧美精品一区二区三区| 国产精品美女黄网| 欧美激情综合| 日本高清一区二区视频| 亚洲国产精品精华液ab| 国产精品suv一区| 日韩av在线网址| japanese色国产在线看视频| 91|九色|视频| 欧美在线视屏| 想看黄色一级片| 国产精品久久久久久久午夜片| 永久免费无码av网站在线观看| 日韩av在线最新| 538视频在线| 国产一区二区三区色淫影院| 一区视频在线看| 亚洲一级Av无码毛片久久精品| 亚洲美女视频一区| 国产乱码精品一区二三区蜜臂| www.久久久久| 9999在线精品视频| 精品一区二区成人免费视频| 国内久久精品视频| 国产精品嫩草影院俄罗斯| 91精品国产欧美一区二区18| 黄网站视频在线观看| 91成人免费观看| 好吊日精品视频| 黄色激情在线观看| 亚洲最新色图| 国产69精品久久久久99| 电影一区中文字幕| 51xx午夜影福利| 高清国产午夜精品久久久久久| 精品在线免费观看视频| 亚洲国产成人av在线| 92国产精品| 亚洲美女网站18| 激情偷乱视频一区二区三区| 日韩av电影网址| 欧美一区二区三区在| 中文字幕在线播放网址| 亚洲已满18点击进入在线看片 | 狠狠色综合日日| av最新在线观看| 日韩视频一区在线观看| 丁香花在线电影| 欧美xxxx黑人又粗又长精品| 男人操女人的视频在线观看欧美| 国产suv精品一区二区三区88区| 日韩在线激情| 一本色道久久88亚洲精品综合| 国产91综合网| 激情五月婷婷网| 久久久精品日本| 国内精品国产成人国产三级粉色 | 黄频免费在线观看| 欧美伦理一区二区| 狠狠久久亚洲欧美| www.av片| 2019国产精品| 91精品国产乱码久久| 欧美极品美女视频网站在线观看免费| 欧美交a欧美精品喷水| 美女一区二区三区视频| 一区二区高清免费观看影视大全 | 国产亚洲制服色| av小说天堂网| 日韩免费在线免费观看| 夜间精品视频| 谁有免费的黄色网址| 日韩欧美国产精品| 日本精品另类| 亚洲 欧美 综合 另类 中字| 久久精品视频在线免费观看| 国产aⅴ一区二区三区| 国产精品www色诱视频| 极品av少妇一区二区| 熟女少妇a性色生活片毛片| 日韩电影视频免费| 九九九视频在线观看|