摘要:不過按照經驗來說,這類異常要么盡量避免,要么出現了就要做異常處理,從而保證程序的健壯性。業務是千變萬化,但是它們可能產生的異常處理方式是不會變化的,按照這個思路去做異常處理即可。
前言:說到異常體系,可能對于一些初入職場的老鐵會很頭痛,不能夠很清晰的描述異常是個什么情況。那么本文將通過打流水仗的方式給大家介紹一下工作中涉及的異常知識。首先能看到本文,說明也對異常是有了解的,所以文章開頭就通過一些概念和小例子快速熟悉一下異常,緊接著介紹異常體系,對于理解整個異常體系架構非常有幫助,最后介紹了非常非常重要的自定義異常,學會了這些,在工作中遇到的常見異常問題,處理起來一定都會游刃有余啦。異常概述 異常
異常就是在程序的運行過程中所發生的不正常的事件,它會中斷正在運行的程序
異常處理Java 編程語言使用異常處理機制為程序提供了錯誤處理的能力,好處就是:如果代碼中存在了異常,但是進行了捕獲處理,那么程序就會繼續運行下去,不會因為一個異常導致程序中斷運行。
例子1:如果程序可能存在異常但是沒有做異常處理,那么將會導致程序不能正常的運行下去:
public class ExceptionTest { public static void main(String[] args) { int a = 10; int b = 0; int c = a / b; System.out.println(c); System.out.println("輸出了本句話嗎"); } } 輸出結果是: Exception in thread "main" java.lang.ArithmeticException: / by zero at cn.caijiajia.cn.caijiajia.exception.ExceptionTest.main(ExceptionTest.java:12)
例子2:如果程序可能存在異常并做了異常處理,那么程序就會正常的運行下去:
public class ExceptionTest { public static void main(String[] args) { try { int a = 10; int b = 0; int c = a / b; System.out.println(c); System.out.println("異常代碼下面的代碼將都不會執行"); } catch (ArithmeticException e) { System.out.println("處理異常的代碼"); } System.out.println("異常處理代碼下面的程序將會繼續執行而不會程序中斷"); } } 輸出結果是: Exception in thread "main" java.lang.ArithmeticException: / by zero at cn.caijiajia.cn.caijiajia.exception.ExceptionTest.main(ExceptionTest.java:12) 處理異常的代碼 異常處理代碼下面的程序將會繼續執行而不會程序中斷Java 中如何處理異常 異常處理的 5 個關鍵字
try:執行可能產生異常的代碼
catch:捕獲異常并對異常情況做相應處理
finally:無論是否發生異常,代碼總能執行。(釋放資源,關閉數據庫連接)
throws:聲明可能拋出的各種異常(受檢異常較多)
throw:手動的拋出異常(手動拋出我們自定義的異常較多)
情況一:沒產生異常
public void method() { try { // 代碼段① [正常業務邏輯代碼,此處不會產生異常] } catch (Exception e) { // 代碼段② [對異常處理的代碼段] } // 代碼段③ [正常業務邏輯代碼] } 運行結果: 代碼段① 代碼段③
情況二:產生異常并捕獲異常
public void method() { try { // 異常代碼段① [正常業務邏輯代碼,此處會產生異常] // 代碼段② [正常業務邏輯代碼] } catch (Exception e) { // 代碼段③ [對異常處理的代碼段] } // 代碼段④ [正常業務邏輯代碼] } 運行結果: 代碼段① 代碼段③ 代碼段④ 注意:如果想要正常的 代碼段② 執行,那么可以把代碼段從 trycatch 里面提出來,和 代碼段④ 放在一起,當異常處理完之后,就可以同時去執行 代碼段② 和 代碼段④ 了。
情況三:產生異常并捕獲異常,但是捕獲異常類型不匹配產生異常類型
public void method() { try { // 異常代碼段① [正常業務邏輯代碼,此處會產生角標越界異常] // 代碼段② [正常業務邏輯代碼] } catch (IOException e) { // 代碼段③ [對異常處理的代碼段] } // 代碼段④ [正常業務邏輯代碼] } 運行結果: 代碼段① 注意:如果捕獲異常類型和產生的異常類型不匹配,那么就和沒有處理異常情況一樣了,trycatch 后面的代碼段將都不會執行,發生異常就會導致程序中斷運行異常體系 異常類層次圖 Error 和 Exception
Error 類和 Exception 類的父類都是 Throwable 類
Error 類一般是指與虛擬機相關的問題,如系統崩潰,虛擬機錯誤,內存空間不足,方法調用棧溢等。對于這類錯誤的導致的應用程序中斷,僅靠程序本身無法恢復和和預防,遇到這樣的錯誤,建議讓程序終止。因此我們在學習的時候主要是學會 Exception。
Exception 類表示程序可以處理的異常,可以捕獲且可能恢復。遇到這類異常,應該盡可能處理異常,使程序恢復運行,而不應該隨意終止異常。
Exception 異常分類及處理Exception 異常主要分為兩大類:Checked Exception,Unchecked Exception;即受檢異常和非受檢異常(運行時異常)
Checked Exception:受檢異常,即 Java 程序必須顯式處理的異常,如果程序沒有處理 Checked 異常,該程序在編譯時就會發生錯誤無法編譯。例如圖中所示的 IOException
處理受檢異常通過有如下兩種方式:
方式一:通過 trycatch 顯式處理異常,否則編譯不通過
public class ExceptionTest { public static void main(String[] args) { try { // 通過 trycatch 顯示處理異常 FileInputStream fis = new FileInputStream(new File("")); } catch (IOException e) { e.printStackTrace(); } } }
方式二:通過 throws 拋出異常,讓上層來處理異常,否則編譯不通過
public class ExceptionTest { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream(new File("")); } }
Unchecked Exception:非受檢異常,即 RuntimeException 運行時異常。這些異常程序可以選擇捕獲處理,也可以不處理。這些異常一般是由程序邏輯錯誤引起的,程序應該從邏輯角度盡可能避免這類異常的發生。比如常見的 NullPointerException、IndexOutOfBoundsException 就是運行時異常。不過按照經驗來說,這類異常要么盡量避免,要么出現了就要做異常處理,從而保證程序的健壯性。
處理運行時異常通過有如下兩種方式:
方式一:常見的空指針處理
// 通過寫偽代碼來演示其處理流程 if (對象 == null) { // 處理對象為 null 的邏輯 } else { // 處理對象不為 null 的邏輯 }
方式二:跟業務相關異常,拋出自定義異常
// 通過手機號注冊業務邏輯 User user = dao.getByPhone(phone); if (user != null) { // 說明此手機號碼已經被注冊,那么就拋出業務異常(即自定義異常) throw new MyRuntimeException("改用戶已注冊"); } // 如果沒有注冊,繼續走注冊流程代碼
總結:通過本小節異常分類及處理可以發現,受檢異常處理起來很簡單,因為程序如果不做顯式處理,那么就會編譯不通過,強制要求處理;而運行時異常則是看心情處理的,但是如果想要公司代碼更加健壯,更少的出現問題,最好要做一下異常處理;但是如果做這個處理呢?對于這種運行時異常,大部分都是和業務相關的,比如手機號注冊例子;這種情況下在 Java 的異常體系中并沒有相關異常類做處理,因為 Java 不管在智能,也不可能知道我們的業務情況,當然就不會針對業務提供一些異常類供我們使用,因此為了解決這個問題,自定義異常就出現了,它對于我們處理業務中產生的運行時異常非常非常重要,接下來就來學習自定義異常。
自定義異常 產生原因Java 現有的異常類不能滿足更多的業務異常處理,因此我們要自定義合適的異常類來處理業務異常。
如何自定義異常類第一步:聲明一個類繼承 Exception 或其子類
那么我們聲明的這個類到底繼承誰呢?Exception?RuntimeException?
答案是:RuntimeException
原因是:看了上面的異常類層次圖,應該也能發現,Exception 下面有兩大類子類,受檢異常和運行時異常,如果我們自定義的類繼承了 Exception,則就會因為受檢異常的存在而變成了受檢異常類,這個時候我們自定義的異常類,如果在程序中使用,那么就必須顯式處理異常,要么 trycatch,要么拋出給上層;這樣一來,使得我們的程序很混亂,而且并沒有達到我們預期的結果。然后當我們自定義的類繼承了 RuntimeException 之后,當我們程序中想要使用的時候,直接 new 一個即可,而不再需要顯式去再多做處理了。
第二步:自定義異常類應至少包含四個構造方法
public class MyException extends RuntimeException { public MyException() {} public MyException(String msg) { super(msg); } public MyException(Throwable throwable) { super(throwable); } public MyException(String msg, Throwable throwable) { super(msg, throwable); } }
第三步:在程序中使用我們的自定義異常
public void testException() { User user = dao.getByPhone(phone); if (user != null) { // 因為 MyException 是繼承 RuntimeException,所以這里直接拋出異常而不用做其它處理 throw new MyException("該手機號已被注冊"); } // ... } 注:沒錯,這里又使用了這個手機號注冊的例子,因為這個就是實實在在的在業務中的異常處理。業務是千變萬化,但是它們可能產生的異常處理方式是不會變化的,按照這個思路去做異常處理即可。
tips:如上自定義的異常類中的構造方法是最基本的幾個。每家公司的自定義異常可能都會有區別,比如定義一個 SuperException 類實現了 RuntimeException,然后在自定義 ClientException,ServerException 再去繼承 SuperException;那么這就是一套自定義體系了,分為客戶端異常和服務端異常,在需要做異常處理的地方使用對應的異常類并拋出異常錯誤信息即可了。再比如可能有的公司會在自定義異常類中在定義一些字段,code,msg 等,來代表某些業務碼和對應的錯誤信息等。不管怎么樣,我們只要了解自定義異常的原理后,面對哪個公司的自定義異常體系我們都能夠輕松應對。
異常總結通過本文的學習,一定要掌握兩個知識,一個是異常體系,要分清受檢異常和運行時異常;另一個就是自定義異常,知道如何自定義異常和如何使用自定義異常。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/68165.html
摘要:挺多人咨詢的,異常處理用切面注解去實現去全局異常處理。全局異常處理類,代碼如下代碼解析如下抽象類是用來處理全局錯誤時進行擴展和實現注解標記的切面排序,值越小擁有越高的優先級,這里設置優先級偏高。 本文內容 為什么要全局異常處理? WebFlux REST 全局異常處理實戰 小結 摘錄:只有不斷培養好習慣,同時不斷打破壞習慣,我們的行為舉止才能夠自始至終都是正確的。 一、為什么要全局...
摘要:前言如題,今天介紹是如何統一處理全局異常的。主要是用于異常攔截出獲取并將設置到消息類中返回。狀態碼異常攔截類通過加入來聲明該類可攔截請求,同時在方法加入并在該注解中指定要攔截的異常類。測試訪問測試正常返回數據結果。 微信公眾號:一個優秀的廢人如有問題或建議,請后臺留言,我會盡力解決你的問題。 前言 如題,今天介紹 SpringBoot 是如何統一處理全局異常的。SpringBoot 中...
摘要:利用前面所述的方法,這個例子可以用方法引用改寫成下面的樣子構造函數引用對于一個現有構造函數,你可以利用它的名稱和關鍵字來創建它的一個引用。 第三章 Lambda表達式 函數式接口 函數式接口就是只定義一個抽象方法的接口,哪怕有很多默認方法,只要接口只定義了一個抽象方法,它就仍然是一個函數式接口。 常用函數式接口 showImg(https://segmentfault.com/img...
摘要:當我們希望能界定這二者之間的區別時,我們將第一種稱為純粹的函數式編程,后者稱為函數式編程。函數式編程我們的準則是,被稱為函數式的函數或方法都只能修改本地變量。另一種觀點支持引用透明的函數式編程,認為方法不應該有對外部可見的對象修改。 一、實現和維護系統 1.共享的可變數據 如果一個方法既不修改它內嵌類的狀態,也不修改其他對象的狀態,使用return返回所有的計算結果,那么我們稱其為純粹...
摘要:前言如題,今天介紹的聲明式事務。提供一個注解在配置類上來開啟聲明式事務的支持。而在配置里還開啟了對聲明式事務的支持,代碼如下所以在中,無須顯式開啟使用注解。源碼下載后語以上為聲明式事務的教程。 微信公眾號:一個優秀的廢人如有問題或建議,請后臺留言,我會盡力解決你的問題。 前言 如題,今天介紹 SpringBoot 的 聲明式事務。 Spring 的事務機制 所有的數據訪問技術都有事務處...
閱讀 2805·2021-11-22 14:44
閱讀 545·2021-11-22 12:00
閱讀 3686·2019-08-30 15:54
閱讀 1576·2019-08-29 17:15
閱讀 1903·2019-08-29 13:50
閱讀 1113·2019-08-29 13:17
閱讀 3519·2019-08-29 13:05
閱讀 1184·2019-08-29 11:31