如果你对java的异常处理头皮发麻,那就进来吧
目錄:
1.異常概念
2.異常架構(gòu)
3.受檢查異常和不受檢查異常
4.異常處理綜合概括
5.JVM 是如何處理異常的
6.拋出異常,聲明異常和捕獲異常
7.finally
8.throw和throws的區(qū)別
9.異常注意點
10.關于異常編程習慣
1.異常概念
簡單說就是不正常運行,最終導致JVM的非正常停止。
異常本身是一個類,產(chǎn)生異常就是創(chuàng)建異常對象并拋出了一個異常對象。Java處理異常的方式是中斷處理。
異常是不是語法問題,如果是語法錯誤編譯的時候就會報錯,根本不會運行
2.異常架構(gòu)
(1)基本框架:
(2)Throwable:
所在位置:java.lang.Throwable
Throwable 是 Java 語言中所有錯誤與異常的超類。
Throwable 包含兩個子類:Error(錯誤)和 Exception(異常),它們通常用于指示發(fā)生了異常情況。
(3)Error(錯誤)
所在位置java.lang.Error
定義:Error 類及其子類。程序中無法處理的錯誤,表示運行應用程序中出現(xiàn)了嚴重的錯誤。
特點:此類錯誤一般表示代碼運行時 JVM 出現(xiàn)問題,此類錯誤發(fā)生時,JVM 將終止線程。
這些錯誤是不受檢異常,非代碼性錯誤
(4)Exception
所在位置:java.lang.Exception
程序本身可以捕獲并且可以處理的異常。Exception 這種異常又分為兩類:運行時異常和編譯時異常。
| 運行時異常 | RuntimeException 類及其子類,表示 JVM 在運行期間可能出現(xiàn)的異常。 | Java 編譯器不會檢查它。也就是說,當程序中可能出現(xiàn)這類異常時,倘若既"沒有通過throws聲明拋出它",也"沒有用try-catch語句捕獲它",還是會編譯通過。比如NullPointerException空指針異常、ArrayIndexOutBoundException數(shù)組下標越界異常等。此類異常屬于不受檢異常,一般是由程序邏輯錯誤引起的,在程序中可以選擇捕獲處理,也可以不處理。雖然 Java 編譯器不會檢查運行時異常,但是我們也可以通過 throws 進行聲明拋出,也可以通過 try-catch 對它進行捕獲處理。如果產(chǎn)生運行時異常,則需要通過修改代碼來進行避免。RuntimeException 異常會由 Java 虛擬機自動拋出并自動捕獲(就算我們沒寫異常捕獲語句運行時也會拋出錯誤!!) |
| 編譯時異常 | Exception 中除 RuntimeException 及其子類之外的異常。 | Java 編譯器會檢查它。如果程序中出現(xiàn)此類異常,比如 ClassNotFoundException(沒有找到指定的類異常),IOException(IO流異常),要么通過throws進行聲明拋出,要么通過try-catch進行捕獲處理,否則不能通過編譯。在程序中,通常不會自定義該類異常,而是直接使用系統(tǒng)提供的異常類。該異常我們必須手動在代碼里添加捕獲語句來處理該異常。 |
3.受檢查異常和不受檢查異常
(1)受檢查異常:
編譯器要求必須處理的異常。正確的程序在運行過程中,經(jīng)常容易出現(xiàn)的、符合預期的異常情況。一旦發(fā)生此類異常,就必須采用某種方式進行處理。除 RuntimeException 及其子類外,其他的 Exception 異常都屬于受檢異常。編譯器會檢查此類異常,也就是說當編譯器檢查到應用中的某處可能會此類異常時,將會提示你處理本異常——要么使用try-catch捕獲,要么使用方法簽名中用 throws 關鍵字拋出,否則編譯不通過。
(2)不受檢查異常:
編譯器不會進行檢查并且不要求必須處理的異常,也就說當程序中出現(xiàn)此類異常時,即使我們沒有try-catch捕獲它,也沒有使用throws拋出該異常,編譯也會正常通過。該類異常包括運行時異常(RuntimeException極其子類)和錯誤(Error)。
4.異常處理的綜合概括
(1)綜合圖解:
(2)拋出異常:
如果你覺得解決不了某些異常問題,且不需要調(diào)用者處理,那么你可以拋出異常。throw關鍵字作用是在方法內(nèi)部拋出一個Throwable類型的異常。任何Java代碼都可以通過throw語句拋出異常。
(3)捕獲異常:
程序通常在運行之前不報錯,但是運行后可能會出現(xiàn)某些未知的錯誤,但是還不想直接拋出到上級,那么就需要通過try…catch…的形式進行異常捕獲,之后根據(jù)不同的異常情況來進行相應的處理。
(4)如何選擇解決異常的方式:
5. JVM 是如何處理異常的?
在一個方法中如果發(fā)生異常,這個方法會創(chuàng)建一個異常對象,并轉(zhuǎn)交給 JVM,該異常對象包含異常名稱,異常描述以及異常發(fā)生時應用程序的狀態(tài)。創(chuàng)建異常對象并轉(zhuǎn)交給 JVM 的過程稱為拋出異常。可能有一系列的方法調(diào)用,最終才進入拋出異常的方法,這一系列方法調(diào)用的有序列表叫做調(diào)用棧。JVM 會順著調(diào)用棧去查找看是否有可以處理異常的代碼,如果有,則調(diào)用異常處理代碼。當 JVM 發(fā)現(xiàn)可以處理異常的代碼時,會把發(fā)生的異常傳遞給它。如果 JVM 沒有找到可以處理該異常的代碼塊,JVM 就會將該異常轉(zhuǎn)交給默認的異常處理器(默認處理器為 JVM 的一部分),默認異常處理器打印出異常信息并終止應用程序。
6.拋出異常,聲明異常和捕獲異常
(1)拋出異常:throw
throw用在方法內(nèi),后面接一個異常對象,使用格式為throw new 異常類名(參數(shù));將這個異常對象傳遞到調(diào)用者處,并結(jié)束當前方法的執(zhí)行,結(jié)束調(diào)用此方法的方法的執(zhí)行
一般的我們用throw拋出一個指定的異常對象,可以有以下兩個用途
1.創(chuàng)建一個異常對象,然后封裝一些提示信息
2.將異常對象告知給調(diào)用者
那么怎能理解呢:
運行結(jié)果:
JVM找不到處理異常代碼,默認異常處理器打印出異常信息并終止應用程序。`
(2)異常聲明:throws
**關鍵字throws運用于方法聲明之上,throws格式為修飾符 返回值類型 方法名(參數(shù)) throws 異常類名1,異常類名2…{ },用于表示當前方法不處理異常,而是提醒該方法的調(diào)用者來處理異常(拋出的異常).**將問題標識出來,報告給調(diào)用者如果方法內(nèi)通過throw拋出了編譯時異常,而沒有捕獲處理(稍后講解該方式),那么必須通過throws進行聲明,讓調(diào)用者去處理。
這里還有一點注意聲明的異常不一定會被拋出,聲明的是可能拋出異常的類型
運行結(jié)果:
JVM找不到處理異常代碼,默認異常處理器打印出異常信息并終止應用程序。
(3)捕獲異常;try.......catch
我們聲明一個異常,并不代表異常被解決了,而是把異常交給方法調(diào)用者去處理如果拋出一個編譯時異常后,不進行聲明,那么就可以通過捕獲異常并處理異常
捕獲異常的格式:
try{ 有可能會出現(xiàn)拋出異常的代碼 }catch(異常類型 e) {處理方式 }他倆不能單獨使用
例子:
運行結(jié)果:
這時候異常就被處理了不會再有異常提示
有時我們會從 catch 中拋出一個異常,目的是為了改變異常的類型。
多用于在多系統(tǒng)集成時,當某個子系統(tǒng)故障,異常類型可能有多種,
可以用統(tǒng)一的異常類型向外暴露,不需暴露太多內(nèi)部異常細節(jié)。
當我們多個異常使用捕獲我們的處理方式:
1.多個異常分別處理
2.多個異常一次捕獲,多次處理
3.多個異常一次捕獲一次處理
第一種就不用費力去舉例了多個try…catch么
第二種:
注意:這種異常處理方式,要求多個catch中的異常不能相同,并且若catch中的多個異常之間有子父類異常的關系,那么子類異常要求在上面的catch處理,父類異常在下面的catch處理。
第三種:
private static void readFile(String filePath) {try {// code} catch (FileNotFoundException | UnknownHostException e) {// handle FileNotFoundException or UnknownHostException}7.finally
(1)finally是干嘛用的:
當方法中發(fā)生異常,異常處之后的代碼不會再執(zhí)行,如果我們還用必要的代碼要執(zhí)行那么finally就解決了這個問題 finally中的代碼塊時一定會執(zhí)行的
(2)什么代碼必須執(zhí)行:
**當我們在try語句塊中打開了一些物理資源(磁盤文件/網(wǎng)絡連接/數(shù)據(jù)庫連接等),**我們都得在使用完之后,最終關閉打開的資源。
(3)finally的用法:
try.....catch.....finally
運行結(jié)果:
當只用在try和catch中調(diào)用退出jvm的相關的方法finally才不會執(zhí)行否則都會執(zhí)行
還有一點那就是try和catch有return語句:
finally語句塊將在方法返回之前被執(zhí)行,另外finally語句中也可以有return語句,那么finally中的return語句就會替換try catch里邊的return
運行結(jié)果:
8.throw和throws的區(qū)別
1.throw用在方法體內(nèi), throws用在方法聲明后面,表示再拋出異常,由該方法的調(diào)用者來處理。
2.throw是具體向外拋異常的,拋出的是一個異常實例 throws聲明了是哪種類型的異常,使它的調(diào)用者可以捕獲這個異常
3.throw,如果執(zhí)行了,那么一定是拋出了某種異常了,但是throws表示可能出現(xiàn),但不一定
4.同時出現(xiàn)的時候,throws出現(xiàn)在函數(shù)頭、throw出現(xiàn)在函數(shù)體,兩種不會由函數(shù)去處理,真正的處理由函數(shù)的上層調(diào)用處理
9.異常注意點
1.父類方法沒有拋出異常,子類重寫父類該方法時也不可拋出異常。此時子類產(chǎn)生該異常,只能捕獲處理,不能聲明拋出
2.如果父類拋出了多個異常,子類重寫父類方法時,拋出和父類相同的異常或者是父類異常的子類或者不拋出異常。
3.finally不能單獨使用,try可以和finally連用不帶catch但是一定要聲明異常
4.不是只有編譯時的檢查異常才會被捕獲,運行的異常可以被JVM捕獲10.異常編譯規(guī)范
五、編程習慣:
(1)在寫程序時,對可能會出現(xiàn)異常的部分通常要用try{…}catch{…}去捕捉它并對它進行處理;
(2)用try{…}catch{…}捕捉了異常之后一定要對在catch{…}中對其進行處理,那怕是最簡單的一句輸出語句,或棧輸入e.printStackTrace();
(3)如果是捕捉IO輸入輸出流中的異常,一定要在try{…}catch{…}后加finally{…}把輸入輸出流關閉;
(4)如果在函數(shù)體內(nèi)用throw拋出了某種異常,最好要在函數(shù)名中加throws拋異常聲明,然后交給調(diào)用它的上層函數(shù)進行處理。
總結(jié)
以上是生活随笔為你收集整理的如果你对java的异常处理头皮发麻,那就进来吧的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: System类、包装类、Math类、Ra
- 下一篇: 浅谈java内存分析和垃圾收集器