溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java中檢查型異常與非檢查型異常的區(qū)別是什么

發(fā)布時(shí)間:2020-12-04 16:25:47 來(lái)源:億速云 閱讀:810 作者:Leah 欄目:編程語(yǔ)言

本篇文章給大家分享的是有關(guān)Java中檢查型異常與非檢查型異常的區(qū)別是什么,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。

        對(duì)于因?yàn)榫幊体e(cuò)誤而導(dǎo)致的異常,或者是不能期望程序捕獲的異常(解除引用一個(gè)空指針,數(shù)組越界,除零,等等),為了使開(kāi)發(fā)人員免于處理這些異常,一些異常被命名為非檢查型異常(即那些繼承自 RuntimeException 的異常)并且不需要進(jìn)行聲明。

Checked Exception和Unchecked Exception的幾點(diǎn)不同之處
        方法簽名是否需要聲明exception,調(diào)用該方法時(shí)是否需要捕獲exception,exception產(chǎn)生的時(shí)候JVM控制程序的狀態(tài)。

Sun 的“The Java Tutorial”觀點(diǎn)
        因?yàn)?Java 語(yǔ)言并不要求方法捕獲或者指定運(yùn)行時(shí)異常,因此編寫(xiě)只拋出運(yùn)行時(shí)異常的代碼或者使得他們的所有異常子類都繼承自RuntimeException ,對(duì)于程序員來(lái)說(shuō)是有吸引力的。這些編程捷徑都允許程序員編寫(xiě) Java 代碼而不會(huì)受到來(lái)自編譯器的所有挑剔性錯(cuò)誤的干擾,并且不用去指定或者捕獲任何異常。盡管對(duì)于程序員來(lái)說(shuō)這似乎比較方便,但是它回避了 Java 的捕獲或者指定要求的意圖,并且對(duì)于那些使用您提供的類的程序員可能會(huì)導(dǎo)致問(wèn)題。

        檢查型異常代表關(guān)于一個(gè)合法指定的請(qǐng)求的操作的有用信息,調(diào)用者可能已經(jīng)對(duì)該操作沒(méi)有控制,并且調(diào)用者需要得到有關(guān)的通知 —— 例如,文件系統(tǒng)已滿,或者遠(yuǎn)端已經(jīng)關(guān)閉連接,或者訪問(wèn)權(quán)限不允許該動(dòng)作。

        如果您僅僅是因?yàn)椴幌胫付ó惓6鴴伋鲆粋€(gè) RuntimeException ,或者創(chuàng)建RuntimeException 的一個(gè)子類,那么您換取到了什么呢?您只是獲得了拋出一個(gè)異常而不用您指定這樣做的能力。換句話說(shuō),這是一種用于避免文檔化方法所能拋出的異常的方式。在什么時(shí)候這是有益的?也就是說(shuō),在什么時(shí)候避免注明一個(gè)方法的行為是有益的?答案是“幾乎從不?!?br/>

        換句話說(shuō),Sun 告訴我們檢查型異常應(yīng)該是準(zhǔn)則。該教程通過(guò)多種方式繼續(xù)說(shuō)明,通常應(yīng)該拋出異常,而不是 RuntimeException —— 除非您是 JVM。

        在 Effective Java: Programming Language Guide一書(shū)中(請(qǐng)參閱參考資料),Josh Bloch 提供了下列關(guān)于檢查型和非檢查型異常的知識(shí)點(diǎn),這些與 “The Java Tutorial” 中的建議相一致(但是并不完全嚴(yán)格一致):

第 39 條:只為異常條件使用異常。也就是說(shuō),不要為控制流使用異常,比如,在調(diào)用 Iterator.next() 時(shí)而不是在第一次檢查Iterator.hasNext() 時(shí)捕獲NoSuchElementException 。

第 40 條:為可恢復(fù)的條件使用檢查型異常,為編程錯(cuò)誤使用運(yùn)行時(shí)異常。這里,Bloch 回應(yīng)傳統(tǒng)的 Sun 觀點(diǎn) —— 運(yùn)行時(shí)異常應(yīng)該只是用于指示編程錯(cuò)誤,例如違反前置條件。

第 41 條:避免不必要的使用檢查型異常。換句話說(shuō),對(duì)于調(diào)用者不可能從其中恢復(fù)的情形,或者惟一可以預(yù)見(jiàn)的響應(yīng)將是程序退出,則不要使用檢查型異常。

第 43 條:拋出與抽象相適應(yīng)的異常。換句話說(shuō),一個(gè)方法所拋出的異常應(yīng)該在一個(gè)抽象層次上定義,該抽象層次與該方法做什么相一致,而不一定與方法的底層實(shí)現(xiàn)細(xì)節(jié)相一致。例如,一個(gè)從文件、數(shù)據(jù)庫(kù)或者 JNDI 裝載資源的方法在不能找到資源時(shí),應(yīng)該拋出某種ResourceNotFound 異常(通常使用異常鏈來(lái)保存隱含的原因),而不是更底層的IOException 、SQLException 或者NamingException 。

一、Java中異常概述

1.1Java異常結(jié)構(gòu)

        Throwable可以用來(lái)表示任何可以被作為異常拋出的類。Throwable對(duì)象派生出兩種類型:Error和Exception,前者用來(lái)表示編譯時(shí)和系統(tǒng)錯(cuò)誤,程序員往往不必關(guān)心;后者是可以被拋出的基本類型,需要程序員關(guān)注。RuntimeException是Exception的派生類,不同點(diǎn)將在2.2與2.3小結(jié)中描述。

       Java的異常(Exception)按照編譯器檢查方式又可以分為檢查型異常(CheckedException)和非檢查型異常(UncheckedException)。

1.2檢查型異常(CheckedException)

        在Java中所有不是RuntimeException派生的Exception都是檢查型異常。當(dāng)函數(shù)中存在拋出檢查型異常的操作時(shí)該函數(shù)的函數(shù)聲明中必須包含throws語(yǔ)句。調(diào)用改函數(shù)的函數(shù)也必須對(duì)該異常進(jìn)行處理,如不進(jìn)行處理則必須在調(diào)用函數(shù)上聲明throws語(yǔ)句。

        檢查型異常是JAVA首創(chuàng)的,在編譯期對(duì)異常的處理有強(qiáng)制性的要求。在JDK代碼中大量的異常屬于檢查型異常,包括IOException,SQLException等等。

1.3非檢查型異常(UncheckedException) 

       在Java中所有RuntimeException的派生類都是非檢查型異常,與檢查型異常相對(duì)拋出非檢查型異??梢圆辉诤瘮?shù)聲明中添加throws語(yǔ)句,調(diào)用函數(shù)上也不需要強(qiáng)制處理。

        常見(jiàn)的NullPointException,ClassCastException是常見(jiàn)的非檢查型異常。非檢查型異常 可以不使用try...catch進(jìn)行處理,但是如果有異常產(chǎn)生,則異常將由JVM進(jìn)行處理。對(duì)于RuntimeException的子類最好也使用異常處理機(jī)制。雖然RuntimeException的異??梢圆皇褂胻ry...catch進(jìn)行處理,但是如果一旦發(fā)生異常,則肯定會(huì)導(dǎo)致程序中斷執(zhí)行,所以,為了保證程序再出錯(cuò)后依然可以執(zhí)行,在開(kāi)發(fā)代碼時(shí)最好使用try...catch的異常處理機(jī)制進(jìn)行處理。

1.4異常的關(guān)鍵字

        Java異常處理涉及到五個(gè)關(guān)鍵字,分別是:try、catch、finally、throw、throws

        五個(gè)關(guān)鍵字的相關(guān)語(yǔ)法略。

二、異常處理方式

2.1異常鏈

        在JDK1.4以后版本中,Throwable類支持異常鏈機(jī)制。Throwable 包含了其線程創(chuàng)建時(shí)線程執(zhí)行堆棧的快照。它還包含了給出有關(guān)錯(cuò)誤更多信息的消息字符串。最后,它還可以包含 cause(原因):另一個(gè)導(dǎo)致此 throwable 拋出的 throwable。它也稱為異常鏈 設(shè)施,因?yàn)?cause 自身也會(huì)有 cause,依此類推,就形成了異常鏈,每個(gè)異常都是由另一個(gè)異常引起的。

        通俗的說(shuō),異常鏈就是把原始的異常包裝為新的異常類,并在新的異常類中封裝了原始異常類,這樣做的目的在于找到異常的根本原因。

2.2異常的轉(zhuǎn)譯

        異常轉(zhuǎn)譯就是將一種異常轉(zhuǎn)換另一種新的異常并且再拋出的過(guò)程,異常轉(zhuǎn)譯的目的是將系統(tǒng)中出現(xiàn)的不同類型的異常進(jìn)行型別的統(tǒng)一,以便于異常的統(tǒng)一處理。
絕大多數(shù)情況下轉(zhuǎn)譯出的“結(jié)果異?!鳖愋投际亲远x異常,并且在異常轉(zhuǎn)譯過(guò)程中需要將“原始異?!狈胖迷诋惓f溨?。

2.3自定義異常

        自定義異常就是自寫(xiě)的繼承了Exception或RuntimeException的異常類。實(shí)現(xiàn)自定義異常的目的大致可分為以下三種:

        1.使用統(tǒng)一的類型標(biāo)識(shí)多種不同型別的異常。

        2.在產(chǎn)生異常時(shí)更好的進(jìn)行信息傳遞。常見(jiàn)的手段是在異常中定義異常碼,異常信息,環(huán)境對(duì)象等字段。

        3.將檢查型異常轉(zhuǎn)換為非檢查型異常。

三異常處理

3.1關(guān)于檢查型異常與非檢查型異常的爭(zhēng)論

        在實(shí)際編程過(guò)程中使用檢查型異常與非檢查型異常的時(shí)機(jī)從JAVA語(yǔ)言產(chǎn)生的那一天開(kāi)始就已經(jīng)產(chǎn)生。

        最為官方的說(shuō)法可以參考Java最核心設(shè)計(jì)者之一JOSHUA BLOCH的《Effective Java》異常使用章節(jié),他的主張是:對(duì)可恢復(fù)的情況使用檢查型異常,對(duì)編程錯(cuò)誤使用運(yùn)行時(shí)異常。

        雖然上述說(shuō)法有著“皇家血統(tǒng)”但事實(shí)上在我看來(lái)Java的檢查型異常是一個(gè)非常失敗的作品,因?yàn)闄z查型異常具有超強(qiáng)的“污染性”,它的出現(xiàn)所帶來(lái)的麻煩遠(yuǎn)比好處要多得多。我的觀點(diǎn)是:幾乎在所有的情況下都不應(yīng)當(dāng)使用檢查型異常。當(dāng)遇到檢查型異常無(wú)法處理的情況時(shí),應(yīng)該使用異常轉(zhuǎn)譯轉(zhuǎn)換為非檢查型異常再拋出。我非常興奮的看到在Think in Java 4th Edition上作者對(duì)這樣的觀點(diǎn)進(jìn)行了詳細(xì)的描述。

        Java創(chuàng)造檢查型異常的初衷是在編譯期強(qiáng)制程序員對(duì)異常情況進(jìn)行處理,從而使得程序更加的強(qiáng)壯可靠,可是Java的作者忘記了:好的程序設(shè)計(jì)語(yǔ)言能幫助程序員寫(xiě)出好程序,但無(wú)論那種語(yǔ)言都避免不了程序員用它寫(xiě)出壞程序。

        對(duì)于異常處理的關(guān)鍵點(diǎn)并不在于是在編譯期還是運(yùn)行期對(duì)異常進(jìn)行檢查,而在于異常一定要檢查并且需要建立統(tǒng)一的、一致的異常檢查與處理模型。

3.2我的異常處理原則

        1.僅處理當(dāng)前可處理的異常。

        2.對(duì)所有的檢查型異常使用異常轉(zhuǎn)譯。

        3.所有的自定義異常都是非檢查型異常。

        4.異常流程與正常流程進(jìn)行分離,并盡可能的統(tǒng)一處理。

        5.在非異常處理模塊的catch塊中盡可能不記日志。

        6.除非是進(jìn)行資源釋放操作,否則catch塊不應(yīng)為空或者出現(xiàn)e.printTrace

        7.finally塊中不能出現(xiàn)復(fù)雜的操作,且不可以拋出異常,也不可以出現(xiàn)return。

3.3我處理異常的一般方式

        1.將throw語(yǔ)句視為異常流程的起點(diǎn),將Exception對(duì)象視作正常流程向異常流程躍遷過(guò)程中的數(shù)據(jù)載體。

        2.建立統(tǒng)一的自定義異常類型,用以包裝所有檢查型異常。

        3.大多數(shù)情況下僅在程序的主干上建立唯一的異常捕獲點(diǎn),并在這個(gè)點(diǎn)上對(duì)接收到的異常進(jìn)行處理。

以上就是Java中檢查型異常與非檢查型異常的區(qū)別是什么,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI