您好,登錄后才能下訂單哦!
這篇文章主要介紹“Java中重要的錯誤處理機制異常有哪些”,在日常操作中,相信很多人在Java中重要的錯誤處理機制異常有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java中重要的錯誤處理機制異常有哪些”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習吧!
一、異常介紹
什么是異常?
異常是指程序在運行過程中發(fā)生的,由于外部問題導(dǎo)致的程序運行異常事件,異常的發(fā)生往往會中斷程序的運行。在 Java 這種面向?qū)ο蟮木幊陶Z言中,萬物都是對象,異常本身也是一個對象,程序發(fā)生異常就會產(chǎn)生一個異常對象。
異常的分類
Throwable
從圖中可以看到,異常主要有以下類構(gòu)成:
Throwable
Error
Exception
接下來我們就分別介紹一下這幾個基類的作用。
Throwable
Throwable 類是 Java 語言中所有錯誤或異常的頂層父類,其他異常類都繼承于該類。Throwable類有兩個重要的子類:**Exception(異常)**和 「Error(錯誤)」,二者都是 Java 異常處理的重要子類,各自都包含大量子類。
只有當對象是此類或其子類的實例時,才能通過 Java 虛擬機或者 Java throw 語句拋出。類似地,只有此類或其子類才可以是 catch 子句中的參數(shù)類型。
Throwable 對象中包含了其線程創(chuàng)建時線程執(zhí)行堆棧的快照,它還包含了給出有關(guān)錯誤更多信息的消息字符串。
最后,它還可以包含 cause(原因):另一個導(dǎo)致此 throwable 拋出的 throwable。此 cause 設(shè)施在 1.4 版本中首次出現(xiàn)。它也稱為異常鏈設(shè)施,因為 cause 自身也會有 cause,依此類推,就形成了異常鏈,每個異常都是由另一個異常引起的。
Error
Error 是 Throwable 的子類,通常情況下應(yīng)用程序「不應(yīng)該試圖捕獲的嚴重問題」。
Error 是程序無法處理的錯誤,表示運行應(yīng)用程序中較嚴重問題。大多數(shù)錯誤與代碼編寫者執(zhí)行的操作無關(guān),而表示代碼運行時 JVM(Java 虛擬機)出現(xiàn)的問題。
例如:Java虛擬機運行錯誤(Virtual MachineError),當 JVM 不再有繼續(xù)執(zhí)行操作所需的內(nèi)存資源時,將出現(xiàn) OutOfMemoryError。這些異常發(fā)生時,Java虛擬機(JVM)一般會選擇線程終止。
這些錯誤表示故障發(fā)生于虛擬機自身、或者發(fā)生在虛擬機試圖執(zhí)行應(yīng)用時,如Java虛擬機運行錯誤(Virtual MachineError)、類定義錯誤(NoClassDefFoundError)等。這些錯誤是不可查的,因為它們在應(yīng)用程序的控制和處理能力之 外,而且絕大多數(shù)是程序運行時不允許出現(xiàn)的狀況。對于設(shè)計合理的應(yīng)用程序來說,即使確實發(fā)生了錯誤,本質(zhì)上也不應(yīng)該試圖去處理它所引起的異常狀況。在 Java中,錯誤通過Error的子類描述。
Exception
Exception以及它的子類,代表程序運行時發(fā)送的各種不期望發(fā)生的事件??梢员籎ava異常處理機制使用,是異常處理的核心。
Exception 異常主要分為兩類:
「1、非檢查性異常(unchecked exception)」
Error 和 RuntimeException 以及他們的子類。Java語言在編譯時,不會提示和發(fā)現(xiàn)這樣的異常,不要求在程序中處理這些異常。所以我們可以在程序中編寫代碼來處理(使用try…catch…finally)這樣的異常,也可以不做任何處理。對于這些錯誤或異常,我們應(yīng)該修正代碼,而不是去通過異常處理器處理。這樣的異常發(fā)生的原因多半是由于我們的代碼邏輯出現(xiàn)了問題。
例如:
當程序中用數(shù)字除以0時,就會拋出ArithmeticException異常;
在類型轉(zhuǎn)換時,錯誤的強制類型轉(zhuǎn)換會拋出ClassCastException類型轉(zhuǎn)換異常;
當使用集合進行數(shù)組索引越界時就會拋出ArrayIndexOutOfBoundsException異常;
當程序中使用了空對象進行操作時就會拋出注明的空指針NullPointerException異常等。
「常見的非檢查性異常有」:
異常 | 描述 |
---|---|
ArithmeticException | 當出現(xiàn)異常的運算條件時,拋出異常。例如,一個整數(shù)“除以零”時,拋出此類的一個實例。 |
ArrayIndexOutOfBoundsException | 用非法索引訪問數(shù)組時跑出的異常。如果索引為負或大于等于數(shù)組大小,則該索引為非法索引。 |
ArrayStoreException | 試圖將錯誤類型的對象存儲到一個對象數(shù)組時,拋出的異常。 |
ClassCastException | 試圖將對象強制轉(zhuǎn)換為不是同一個類型或其子類的實例時,拋出的異常。 |
IllegalArgumentException | 當向一個方法傳遞非法或不正確的參數(shù)時,拋出該異常。 |
IllegalMonitorStateException | 當某一線程已經(jīng)試圖等待對象的監(jiān)視器,或者通知其他正在等待該對象監(jiān)視器的線程,而該線程本身沒有獲得指定監(jiān)視器時拋出該異常。 |
IllegalStateException | 在非法或不適當?shù)臅r間調(diào)用方法時產(chǎn)生的信號?;蛘哒fJava環(huán)境或應(yīng)用程序沒有處于請求操作所要求的適當狀態(tài)下。 |
IllegalThreadStateException | 線程沒有處于請求操作所要求的適當狀態(tài)時,拋出該異常。 |
IndexOutOfBoundsException | 當某種排序的索引超出范圍時拋出的異常,例如,一個數(shù)組,字符串或一個向量的排序等。 |
NegativeArraySizeException | 如果應(yīng)用程序試圖創(chuàng)建大小為負的數(shù)組時,拋出該異常。 |
NullPointerException | 當應(yīng)用程序在需要操作對象的時候而獲得的對象實例是null時拋出該異常。 |
NumberFormatException | 當應(yīng)用程序試圖將字符串轉(zhuǎn)換成一種數(shù)值類型,但該字符串不能轉(zhuǎn)換為適當格式時,拋出該異常。 |
SecurityException | 由安全管理器拋出的異常,指示存在安全侵犯。 |
StringIndexOutOfBoundsException | 此異常由String方法拋出,說明索引為負或者超出了字符串的大小。 |
「2、檢查性異常(checked exception)」
除了Error 和 RuntimeException的其它異常。Java語言強制要求程序員為這樣的異常做預(yù)備處理工作(使用try…catch…finally或者throws)。在方法中要么用try-catch語句捕獲它并處理,要么用throws子句聲明拋出它,否則編譯不會通過。這樣的異常一般是由程序的運行環(huán)境導(dǎo)致的。因為程序可能被運行在各種未知的環(huán)境下,而程序員無法干預(yù)用戶如何使用他編寫的程序,于是程序員就應(yīng)該為這樣的異常時刻準備著。如SQLException,IOException,ClassNotFoundException 等。
檢查性異常就是指,編譯器在編譯期間要求必須得到處理的那些異常,你必須在編譯期處理了。
「常見的檢查性異常有」:
異常 | 描述 |
---|---|
ClassNotFoundException | 當應(yīng)用程序試圖加載一個類,通過名字查找時卻發(fā)現(xiàn)沒有該類的定義時,拋出該異常。 |
CloneNotSupportedException | 當去克隆一個對象時,發(fā)現(xiàn)該對象沒有實現(xiàn)Cloneable接口時,拋出該異常。 |
IllegalAccessException | 當應(yīng)用程序嘗試通過反射的方式來訪問類、成員變量或調(diào)用方法時,卻無法訪問這些類、成員變量或方法的定義時,拋出該異常。 |
InstantiationException | 當試圖使用Class類中的newInstance方法創(chuàng)建一個類的實例,而制定的類對象因為是一個接口或是一個抽象類而無法實例化時,拋出該異常。 |
InterruptedException | 一個線程被另一個線程中斷時,拋出該異常。 |
NoSuchFieldException | 當找不到指定的變量字段時,拋出該異常、 |
NoSuchMethodException | 當找不到指定的類方法時,拋出該異常。 |
二、初識異常
下面我們通過一個簡單實例,讓大家更直觀的認識一下Java的異常。
下面的代碼會拋出著名的空指針異常:NullPointerException。
public class Test { private int a = 1; private int b = 2; public static void main(String[] args) { Test t1 = new Test(); Test t2 = null; System.out.println(t1.a); System.out.println(t2.a); System.out.println(t2.c()); } public String c() { return "微信公眾號:我是開發(fā)者FTD"; } }
運行程序,控制臺輸出結(jié)果如下:
1 Exception in thread "main" java.lang.NullPointerException at cc.devclub.ftd.Test.main(Test.java:11) Process finished with exit code 1
從控制臺輸出可以看到,程序打印了 “1”,然后在程序的第11行的位置拋出了 「java.lang.NullPointerException」 ,然后程序就終止運行了。
三、異常處理機制
在編寫代碼處理異常時,對于檢查性異常,有兩種不同的處理方式:
使用 「try…catch…finally…」 語句塊處理
在方法中使用 「throws/throw」 關(guān)鍵詞將異常交給方法調(diào)用者去處理
try...catch...finally… 關(guān)鍵字
使用 try 和 catch 關(guān)鍵字可以捕獲異常。
try/catch 代碼塊放在異常可能發(fā)生的地方。
try/catch代碼塊中的代碼稱為保護代碼,使用 try/catch 的語法如下:
try { ... } catch (IOException ioException) { ... } catch (Exception exception) { ... } finally { ... }
「try 塊:」
try塊中放可能發(fā)生異常的代碼。
如果執(zhí)行完try且不發(fā)生異常,則接著去執(zhí)行finally塊中的代碼和finally后面的代碼(如果有的話)。
如果程序發(fā)生異常,則嘗試去匹配對應(yīng)的catch塊。
「catch 塊:」
每一個catch塊用于捕獲并處理一個特定的異常,或者這異常類型的子類。Java7中可以將多個異常聲明在一個catch中。
catch后面的括號定義了異常類型和異常參數(shù)。如果異常與之匹配且是最先匹配到的,則虛擬機將使用這個catch塊來處理異常。
在catch塊中可以使用這個塊的異常參數(shù)來獲取異常的相關(guān)信息。異常參數(shù)是這個catch塊中的局部變量,其它塊不能訪問。
如果當前try塊中發(fā)生的異常在后續(xù)的所有catch中都沒捕獲到,則先去執(zhí)行finally,然后到這個方法的外部調(diào)用者中去匹配異常處理器。
如果try中沒有發(fā)生異常,則所有的catch塊將被忽略。
「需要注意的地方」
1、try塊中的局部變量和catch塊中的局部變量(包括異常變量),以及finally中的局部變量,他們之間不可共享使用。
2、每一個catch塊用于處理一個異常。異常匹配是按照catch塊的順序從上往下尋找的,只有第一個匹配的catch會得到執(zhí)行。匹配時,不僅運行精確匹配,也支持父類匹配,因此,如果同一個try塊下的多個catch異常類型有父子關(guān)系,應(yīng)該將子類異常放在前面,父類異常放在后面,這樣保證每個catch塊都有存在的意義。
3、Java中,異常處理的任務(wù)就是將執(zhí)行控制流從異常發(fā)生的地方轉(zhuǎn)移到能夠處理這種異常的地方去。也就是說:當一個方法的某條語句發(fā)生異常時,這條語句的后面的語句不會再執(zhí)行,它失去了焦點。執(zhí)行流跳轉(zhuǎn)到最近的匹配的異常處理catch代碼塊去執(zhí)行,異常被處理完后,執(zhí)行流會接著在“處理了這個異常的catch代碼塊”后面接著執(zhí)行。
「finally 塊:」
finally塊不是必須的,通常是可選的。
無論異常是否發(fā)生,異常是否匹配被處理,finally中的代碼都會執(zhí)行。
一個try至少要有一個catch塊,否則, 至少要有1個finally塊。但是finally不是用來處理異常的,finally不會捕獲和處理異常,處理異常的只能是catch塊。
finally主要做一些清理工作,如流的關(guān)閉,數(shù)據(jù)庫連接的關(guān)閉等。
finally塊不管異常是否發(fā)生,只要對應(yīng)的try執(zhí)行了,則它一定也執(zhí)行。只有一種方法讓finally塊不執(zhí)行:「System.exit()」 。
大家需要養(yǎng)成**良好的編程習慣是:**在try塊中打開資源,在finally塊中清理并釋放這些資源,以免造成內(nèi)存泄露。
「需要注意的地方:」
1、在同一try…catch…finally…塊中,如果try中拋出異常,且有匹配的catch塊,則先執(zhí)行catch塊,再執(zhí)行finally塊。如果沒有catch塊匹配,則先執(zhí)行finally,然后去到上層的調(diào)用者中尋找合適的catch塊。
2、在同一try…catch…finally…塊中 ,try發(fā)生異常,且匹配的catch塊中處理異常時也拋出異常,那么后面的finally也會執(zhí)行:首先執(zhí)行finally塊,然后去上層調(diào)用者中尋找合適的catch塊。
throws/throw 關(guān)鍵字
「throws 關(guān)鍵字」
如果一個方法內(nèi)部的代碼會拋出檢查性異常(checked exception),而方法自己又沒有對這些異常完全處理掉,則java的編譯器會要求你必須在方法的簽名上使用 「throws」 關(guān)鍵字聲明這些可能拋出的異常,否則編譯不通過。
throws 是另一種處理異常的方式,它不同于try…catch…finally…,throws 關(guān)鍵字僅僅是將方法中可能出現(xiàn)的異常向調(diào)用者拋出,而自己則不具體處理。
采取這種異常處理的原因可能是:方法本身不知道如何處理這樣的異常,或者說讓調(diào)用者處理更好,調(diào)用者需要為可能發(fā)生的異常負責。
「throw 關(guān)鍵字」
我們也可以通過 throw 語句手動顯式的拋出一個異常,throw語句的后面必須是一個異常對象。語法如下:
throw exceptionObject
throw 語句必須寫在方法中,執(zhí)行throw 語句的地方就是一個異常拋出點,它和由JRE自動形成的異常拋出點沒有任何差別。
public void save(User user) { if (user == null) throw new IllegalArgumentException("User對象為空"); //...... }
try-catch-finally 的執(zhí)行順序
try-catch-finally 執(zhí)行順序的相關(guān)問題可以說是各種面試中的「常客」了,尤其是 finally 塊中帶有 return 語句的情況。我們直接看幾道面試題:
「面試題一:」
public static void main(String[] args) { int result = test1(); System.out.println(result); } public static int test1() { int i = 1; try { i++; System.out.println("try block, i = " + i); } catch (Exception e) { i--; System.out.println("catch block i = " + i); } finally { i = 10; System.out.println("finally block i = " + i); } return i; }
大家不妨算一算程序員最終運行的結(jié)果是什么。
輸出結(jié)果如下:
try block, i = 2 finally block i = 10 10
這算一個相當簡單的問題了,沒有坑,下面我們稍微改動一下:
public static int test2() { int i = 1; try { i++; throw new Exception(); } catch (Exception e) { i--; System.out.println("catch block i = " + i); } finally { i = 10; System.out.println("finally block i = " + i); } return i; }
輸出結(jié)果如下:
catch block i = 1 finally block i = 10 10
運行結(jié)果想必也是意料之中吧,程序拋出一個異常,然后被本方法的 catch 塊捕獲并進行了處理。
「面試題二:」
public static void main(String[] args) { int result = test3(); System.out.println(result); } public static int test3() { //try 語句塊中有 return 語句時的整體執(zhí)行順序 int i = 1; try { i++; System.out.println("try block, i = " + i); return i; } catch (Exception e) { i++; System.out.println("catch block i = " + i); return i; } finally { i = 10; System.out.println("finally block i = " + i); } }
輸出結(jié)果如下:
try block, i = 2 finally block i = 10 2
是不是有點疑惑?明明我 try 語句塊中有 return 語句,可為什么最終還是執(zhí)行了 finally 塊中的代碼?
我們反編譯這個類,看看這個 test3 方法編譯后的字節(jié)碼的實現(xiàn):
0: iconst_1 //將 1 加載進操作數(shù)棧 1: istore_0 //將操作數(shù)棧 0 位置的元素存進局部變量表 2: iinc 0, 1 //將局部變量表 0 位置的元素直接加一(i=2) 5: getstatic #3 // 5-27 行執(zhí)行的 println 方法 8: new #5 11: dup 12: invokespecial #6 15: ldc #7 17: invokevirtual #8 20: iload_0 21: invokevirtual #9 24: invokevirtual #10 27: invokevirtual #11 30: iload_0 //將局部變量表 0 位置的元素加載進操作棧(2) 31: istore_1 //把操作棧頂?shù)脑卮嫒刖植孔兞勘砦恢?nbsp;1 處 32: bipush 10 //加載一個常量到操作棧(10) 34: istore_0 //將 10 存入局部變量表 0 處 35: getstatic #3 //35-57 行執(zhí)行 finally中的println方法 38: new #5 41: dup 42: invokespecial #6 45: ldc #12 47: invokevirtual #8 50: iload_0 51: invokevirtual #9 54: invokevirtual #10 57: invokevirtual #11 60: iload_1 //將局部變量表 1 位置的元素加載進操作棧(2) 61: ireturn //將操作棧頂元素返回(2) -------------------try + finally 結(jié)束 ------------ ------------------下面是 catch + finally,類似的 ------------ 62: astore_1 63: iinc 0, 1 ....... .......
從我們的分析中可以看出來,finally 代碼塊中的內(nèi)容始終會被執(zhí)行,無論程序是否出現(xiàn)異常的原因就是,「編譯器會將 finally 塊中的代碼復(fù)制兩份并分別添加在 try 和 catch 的后面」。
可能有人會所疑惑,原本我們的 i 就被存儲在局部變量表 0 位置,而最后 finally 中的代碼也的確將 slot 0 位置填充了數(shù)值 10,可為什么最后程序依然返回的數(shù)值 2 呢?
仔細看字節(jié)碼,你會發(fā)現(xiàn)在 return 語句返回之前,虛擬機會將待返回的值壓入操作數(shù)棧,等待返回,即使 finally 語句塊對 i 進行了修改,但是待返回的值已經(jīng)確實的存在于操作數(shù)棧中了,所以不會影響程序返回結(jié)果。
「面試題三:」
public static int test4() { //finally 語句塊中有 return 語句 int i = 1; try { i++; System.out.println("try block, i = " + i); return i; } catch (Exception e) { i++; System.out.println("catch block i = " + i); return i; } finally { i++; System.out.println("finally block i = " + i); return i; } }
運行結(jié)果:
try block, i = 2 finally block i = 3 3
其實你從它的字節(jié)碼指令去看整個過程,而不要單單死記它的執(zhí)行過程。
你會發(fā)現(xiàn)程序最終會采用 finally 代碼塊中的 return 語句進行返回,而直接忽略 try 語句塊中的 return 指令。
自定義異常
Java 的異常機制中所定義的所有異常不可能預(yù)見所有可能出現(xiàn)的錯誤,某些特定的情境下,則需要我們自定義異常類型來向上報告某些錯誤信息。
而自定義異常類型也是相當簡單的,你可以選擇繼承 Throwable,Exception 或它們的子類,甚至你不需要實現(xiàn)和重寫父類的任何方法即可完成一個異常類型的定義。
例如:
public class MyException extends RuntimeException{ } public class MyException extends Exception{ }
按照國際慣例,自定義的異常應(yīng)該總是包含如下的構(gòu)造函數(shù):
一個無參構(gòu)造函數(shù)
一個帶有String參數(shù)的構(gòu)造函數(shù),并傳遞給父類的構(gòu)造函數(shù)。
一個帶有String參數(shù)和Throwable參數(shù),并都傳遞給父類構(gòu)造函數(shù)
一個帶有Throwable 參數(shù)的構(gòu)造函數(shù),并傳遞給父類的構(gòu)造函數(shù)。
下面是IOException類的完整源代碼,我們可以參考:
public class IOException extends Exception { static final long serialVersionUID = 7818375828146090155L; public IOException() { super(); } public IOException(String message) { super(message); } public IOException(String message, Throwable cause) { super(message, cause); } public IOException(Throwable cause) { super(cause); } }
異常的注意事項
1、當子類重寫父類的帶有 throws聲明的函數(shù)時,其throws聲明的異常必須在父類異常的可控范圍內(nèi)——用于處理父類的throws方法的異常處理器,必須也適用于子類的這個帶throws方法 。這是為了支持多態(tài)。
例如,父類方法throws 的是2個異常,子類就不能throws 3個及以上的異常。父類throws IOException,子類就必須throws IOException或者IOException的子類。
2、Java程序可以是多線程的。每一個線程都是一個獨立的執(zhí)行流,獨立的函數(shù)調(diào)用棧。如果程序只有一個線程,那么沒有被任何代碼處理的異常 會導(dǎo)致程序終止。如果是多線程的,那么沒有被任何代碼處理的異常僅僅會導(dǎo)致異常所在的線程結(jié)束。
也就是說,Java中的異常是線程獨立的,線程的問題應(yīng)該由線程自己來解決,而不要委托到外部,也不會直接影響到其它線程的執(zhí)行。
異常使用時的常見錯誤
1、將異常直接顯示在頁面或客戶端
將異常直接打印在客戶端的例子屢見不鮮,一旦程序運行出現(xiàn)異常,默認情況下容器將異常堆棧信息直接打印在頁面上。從客戶角度來說,任何異常都沒有實際意義,絕大多數(shù)的客戶也根本看不懂異常信息,軟件開發(fā)也要盡量避免將異常直接呈現(xiàn)給用戶,一定要在前端展示層對異常進行封裝后展示。目前絕大多數(shù)應(yīng)用都是前后端分離的模式,這種直接打印異常的情況已經(jīng)相對改善了很多,不過我們在編碼時還是要特別注意下這個原則。
2、忽略異常
如下異常處理只是將異常輸出到控制臺,沒有任何意義。而且這里出現(xiàn)了異常并沒有中斷程序,進而調(diào)用代碼繼續(xù)執(zhí)行,導(dǎo)致更多的異常。
public void retrieveObjectById(Long id) { try { //..some code that throws SQLException } catch (SQLException ex) { /** *了解的人都知道,這里的異常打印毫無意義,僅僅是將錯誤堆棧輸出到控制臺。 * 而在 Production 環(huán)境中,需要將錯誤堆棧輸出到日志。 * 而且這里 catch 處理之后程序繼續(xù)執(zhí)行,會導(dǎo)致進一步的問題*/ ex.printStacktrace(); } }
捕獲了異常缺不進行處理,這是我們在寫代碼時候的大忌,可以重構(gòu)成:
public void retrieveObjectById(Long id) { try { //..some code that throws SQLException } catch (SQLException ex) { throw new RuntimeException("Exception in retieveObjectById”, ex); } finally { //clean up resultset, statement, connection etc } }
3、將異常包含在循環(huán)語句塊中
如下代碼所示,異常包含在 for 循環(huán)語句塊中。
for (int i = 0; i < 100; i++) { try { } catch (XXXException e) { //.... } }
我們都知道異常處理占用系統(tǒng)資源。一看,大家都認為不會犯這樣的錯誤。換個角度,類 A 中執(zhí)行了一段循環(huán),循環(huán)中調(diào)用了 B 類的方法,B 類中被調(diào)用的方法卻又包含 try-catch 這樣的語句塊。褪去類的層次結(jié)構(gòu),代碼和上面如出一轍。
4、利用 Exception 捕捉所有潛在的異常
一段方法執(zhí)行過程中拋出了幾個不同類型的異常,為了代碼簡潔,利用基類 Exception 捕捉所有潛在的異常,如下例所示:
public void retrieveObjectById(Long id) { try { //...拋出 IOException 的代碼調(diào)用 //...拋出 SQLException 的代碼調(diào)用 } catch (Exception e) { //這里利用基類 Exception 捕捉的所有潛在的異常,如果多個層次這樣捕捉,會丟失原始異常的有效信息 throw new RuntimeException("Exception in retieveObjectById”, e); } }
估計大部分程序員都會有這種寫法,為了省事簡便,直接一個頂層的exception來捕獲所有可能出現(xiàn)的異常,這樣雖然可以保證異??隙〞徊蹲降?,但是程序卻無法針對不同的錯誤異常進行對應(yīng)正確的處理,可以重構(gòu)成:
public void retrieveObjectById(Long id) { try { //..some code that throws RuntimeException, IOException, SQLException } catch (IOException e) { //僅僅捕捉 IOException throw new RuntimeException(/*指定這里 IOException 對應(yīng)的錯誤代碼*/code, "Exception in retieveObjectById”, e); } catch (SQLException e) { //僅僅捕捉 SQLException throw new RuntimeException(/*指定這里 SQLException 對應(yīng)的錯誤代碼*/code, "Exception in retieveObjectById”, e); } }
5、異常包含的信息不能充分定位問題
異常不僅要能夠讓開發(fā)人員知道哪里出了問題,更多時候開發(fā)人員還需要知道是什么原因?qū)е碌膯栴},我們知道 java .lang.Exception 有字符串類型參數(shù)的構(gòu)造方法,這個字符串可以自定義成通俗易懂的提示信息。
簡單的自定義信息開發(fā)人員只能知道哪里出現(xiàn)了異常,但是很多的情況下,開發(fā)人員更需要知道是什么參數(shù)導(dǎo)致了這樣的異常。這個時候我們就需要將方法調(diào)用的參數(shù)信息追加到自定義信息中。下例只列舉了一個參數(shù)的情況,多個參數(shù)的情況下,可以單獨寫一個工具類組織這樣的字符串。
public void retieveObjectById(Long id) { try { //..some code that throws SQLException } catch (SQLException ex) { //將參數(shù)信息添加到異常信息中 throw new RuntimeException("Exception in retieveObjectById with Object Id :"+ id, ex); } }
到此,關(guān)于“Java中重要的錯誤處理機制異常有哪些”的學(xué)習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習,快去試試吧!若想繼續(xù)學(xué)習更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。