手机看片精品高清国产日韩,色先锋资源综合网,国产哺乳奶水91在线播放,乱伦小说亚洲色图欧洲电影

幫助中心 >  行業(yè)資訊 >  架構(gòu) >  架構(gòu)設(shè)計(jì)-異常處理

架構(gòu)設(shè)計(jì)-異常處理

2021-04-22 09:28:19 185

我們在設(shè)計(jì)自己的系統(tǒng)或平臺(tái)時(shí),就要考慮如何更加合理的設(shè)計(jì)異常,接下來我們就一起來看異常的設(shè)計(jì)。

一、異常概述

在程序中,異常就是程序在運(yùn)行時(shí)期發(fā)生的問題,在理想的程序環(huán)境中,程序永遠(yuǎn)不會(huì)出現(xiàn)問題,用戶的輸入永遠(yuǎn)都是符合要求,邏輯沒有任何問題,要打開的文件一定存在,類型轉(zhuǎn)換一定是對的,內(nèi)存一直是夠用的.....總之沒有任何問題,但是一旦出現(xiàn)這些描述的反面情況,如果不進(jìn)行合理的處理,系統(tǒng)就不能正常運(yùn)行,系統(tǒng)就無法提供正常的服務(wù)給用戶。

要處理異常就要直到異常是如何發(fā)生的,就必須要知道異常的發(fā)生原因,要知道異常發(fā)生的原因就必須知道異常發(fā)生的場景。在系統(tǒng)中,模塊和模塊之間的交互都可能發(fā)生異常,以JAVA為例,在程序中都是利用Method和其他模塊進(jìn)行交互,那么異常的產(chǎn)生、拋出、聲明和處理都在Method中,如下圖就是java程序,模塊和模塊之間的交互邏輯。


1.png


如圖所示,你寫的方法和外部實(shí)體交互大概可以分為五類:

1.和資源(Resource)交互,見圖⑤處。這里資源的范圍很廣,比如進(jìn)程外部的數(shù)據(jù)庫,文件,SOA服務(wù),其他各種中間件;進(jìn)程內(nèi)的類,方法,線程……都算是資源。

2.給進(jìn)程內(nèi)的其他方法(User Method)提供服務(wù),見圖②處。

3.依賴進(jìn)程內(nèi)的其他方法(Server Method),見圖③處。包括Java平臺(tái)提供的方法和其他第三方供應(yīng)方提供的方法。

4.和系統(tǒng)環(huán)境交互,見圖⑧處。系統(tǒng)環(huán)境可能是直接環(huán)境——JVM,也可能是間接環(huán)境——操作系統(tǒng)或硬件等。

5.給外部實(shí)體提供服務(wù),見圖①處。這種外部實(shí)體一般會(huì)通過容器(或其他類似的機(jī)制)和你的方法進(jìn)行交互。

Java方法和每一類實(shí)體進(jìn)行交互時(shí),都可能發(fā)生異常。當(dāng)和資源交互時(shí),常常會(huì)因?yàn)橘Y源不可用而發(fā)生異常,比如發(fā)生找不到文件、數(shù)據(jù)庫連接錯(cuò)誤、找不到類、找不到方法……等等狀況。有可能是直接產(chǎn)生的,見圖⑤處;有可能是間接產(chǎn)生的,比如圖⑥處發(fā)生異常,Server Method把異常拋給Your Method,圖③處就間接發(fā)生了異常。一般來說,你寫的方法間接發(fā)生這類異常的可能性比直接發(fā)生要大得多,因?yàn)橹苯赢a(chǎn)生這類異常的方法在Java平臺(tái)中已經(jīng)提供了。

異常一般具有如下特點(diǎn):

(1)問題產(chǎn)生于外部依賴,自身邏輯和流程沒有問題。

(2)此類問題通常是暫時(shí)的,服務(wù)端及時(shí)處理可以消除,用戶可以再次使用系統(tǒng)服務(wù)或采取替補(bǔ)方案。

(3)并不影響整體流程運(yùn)行。

當(dāng)給Client端的方法(User Method )提供服務(wù)時(shí),用戶可能會(huì)傳入一些不合法的數(shù)據(jù)(或者其他不恰當(dāng)?shù)氖褂梅椒ǎM(jìn)而影響正常流程運(yùn)行。你的方法應(yīng)該檢查每一個(gè)輸入數(shù)據(jù),如果發(fā)現(xiàn)不合法的數(shù)據(jù),馬上阻止執(zhí)行流程,并通知用戶方法。

當(dāng)調(diào)用服務(wù)方法(Server Method )時(shí),有可能會(huì)發(fā)生兩類異常。一類是你的使用方法不正確,導(dǎo)致服務(wù)中止;一類是服務(wù)方法出了異常,然后傳遞給你的方法。如果是第一種異常,你應(yīng)該檢查并修改你的方法邏輯,消除BUG。對于第二類異常,你要么寫一個(gè)處理器處理,要么繼續(xù)傳遞給上層方法。

當(dāng)和系統(tǒng)環(huán)境交互時(shí),有可能因?yàn)镴VM參數(shù)設(shè)置不當(dāng),有可能因?yàn)槌绦虍a(chǎn)生了大量不必要的對象,也有可能因?yàn)橛补收希ú僮飨到y(tǒng)或硬件出了問題),導(dǎo)致整個(gè)程序不可用。當(dāng)這類異常發(fā)生時(shí),最終用戶沒法選擇其他替代方案,操作到一半的數(shù)據(jù)會(huì)全部丟失。你的方法對這類異常一般沒什么辦法,既不能通過修改主流程邏輯來消除,也不能通過增加異常處理器來處理。所以通常你的方法對這類異常不需要做任何處理。但是你必須檢查進(jìn)程內(nèi)的所有程序和系統(tǒng)環(huán)境是否正常,然后協(xié)調(diào)各方,修改BUG或恢復(fù)環(huán)境。

Java的異常都是發(fā)生在方法內(nèi),所以研究Java異常,要以你設(shè)計(jì)的方法為中心。我們以“你的方法 ”為中心,總結(jié)一下處理辦法:當(dāng)服務(wù)方法告訴“你的方法 ”的主流程邏輯有問題時(shí),就要及時(shí)修復(fù)BUG來消除異常;當(dāng)用戶方法非法使用“你的方法”時(shí),應(yīng)該直接中止主流程,并通知用戶方法,強(qiáng)迫用戶方法使用正確的方式,防止問題蔓延;當(dāng)服務(wù)方法傳遞一個(gè)異常給“你的方法”時(shí),你要判斷“你的方法”是否合適處理這個(gè)異常,如果不合適,傳遞給上層方法,如果合適,寫一個(gè)異常處理器處理這個(gè)異常。當(dāng)系統(tǒng)環(huán)境出了問題,“你的方法”什么也做不了。

以上所述,異常有三類:

(1)檢查性異常:最具代表的檢查性異常是用戶錯(cuò)誤或問題引起的異常,這是程序員無法預(yù)見的。例如要打開一個(gè)不存在文件時(shí),一個(gè)異常就發(fā)生了,這些異常在編譯時(shí)不能被簡單地忽略。

(2)運(yùn)行時(shí)異常:運(yùn)行時(shí)異常是可能被程序員避免的異常。與檢查性異常相反,運(yùn)行時(shí)異常可以在編譯時(shí)被忽略。

(3)錯(cuò)誤:錯(cuò)誤不是異常,而是脫離程序員控制的問題。錯(cuò)誤在代碼中通常被忽略。例如,當(dāng)棧溢出時(shí),一個(gè)錯(cuò)誤就發(fā)生了,它們在編譯也檢查不到的。

剛才以“你的方法”為中心,總結(jié)了在“你的方法”內(nèi)部的處理辦法。現(xiàn)在以“你”為中心,總結(jié)一下方法外部的處理方法:當(dāng)資源不可用的時(shí)候,你應(yīng)該協(xié)調(diào)各方,恢復(fù)資源;當(dāng)發(fā)生系統(tǒng)故障時(shí),你應(yīng)該協(xié)調(diào)各方,恢復(fù)系統(tǒng)。綜上,已經(jīng)基本分析清楚了異常發(fā)生的原因,以及相應(yīng)的應(yīng)對方法。

二、異常的好處

上面已經(jīng)很清楚的闡述了什么異常,并且知道怎么使用異常,那么在程序中使用異常具體有那些好處呢?

1.好處一隔離錯(cuò)誤處理代碼和常規(guī)代碼

 Exception提供了一種方法,把意外發(fā)生時(shí)的細(xì)節(jié)從程序主邏輯中隔離開來。在傳統(tǒng)的編程中,錯(cuò)誤的檢測、報(bào)告和處理通常會(huì)導(dǎo)致像意大利面條那么混亂的代碼。

下面通過一組偽代碼來講解。


11.png


讀取文件正常流程是很簡單的,但是真實(shí)的運(yùn)行過程中,有很多異常情況需要考慮:

(1)當(dāng)文件無法打開,應(yīng)該如何處理?

(2)當(dāng)無法獲取文件的大小,應(yīng)該如何處理?

(3)當(dāng)服務(wù)器內(nèi)存不足,應(yīng)該如何處理?

(4)當(dāng)讀取失敗,應(yīng)該如何處理?

(5)當(dāng)文件無法關(guān)閉,應(yīng)該如何處理?

為了處理這么多異常情況,我們的做法有兩種方式,方式一通過錯(cuò)誤碼來表示每一個(gè)異常發(fā)生的狀態(tài),方式二是通過異常來表示。


12.png


為了保證流程正常進(jìn)行,讀取文件需要檢測錯(cuò)誤、返回狀態(tài),原本很簡單的代碼,通過各種if/else判斷處理,代碼變得很繁瑣,代碼的可讀性變得很糟糕,如果通過第二種方式二,異常代替錯(cuò)誤碼來處理正常流程,我們看看會(huì)發(fā)生什么情況?

示例如下


13.png


從上面的偽代碼可以看出,異常并沒有忽略或者代替你做readFile過程中異常情況處理,而是通過異常處理讓你的關(guān)注點(diǎn)更多的放在核心邏輯的處理,并且提高了代碼的可讀性。

2.好處二在調(diào)用棧中向上傳播錯(cuò)誤

Exception的第二個(gè)優(yōu)勢就是,傳播錯(cuò)誤報(bào)告方法調(diào)用堆棧的能力。比如在一個(gè)應(yīng)用流程中,readFile方法是最終被最上層得調(diào)用間接依賴,如:method1調(diào)用了method2,method2調(diào)用了method3,method3調(diào)用了readFile方法,因?yàn)閞eadFile有很多異常情況需要處理,但是按照調(diào)用層次來看,method1是最終需要處理readFile異常錯(cuò)誤碼的方法,實(shí)現(xiàn)方法也有兩種,方式一:逐層放回錯(cuò)誤碼,直到method1接受到錯(cuò)誤碼;方式二:通過逐層拋出異常,method1處理異常,其他層只關(guān)心上拋。


14.png


上面的偽代碼可以看出,最終只有method1 關(guān)心 readFile 所產(chǎn)生的錯(cuò)誤,方式一將強(qiáng)制要求每個(gè)方法都關(guān)心并返回。如果有一種方式只讓關(guān)心作物的方法才關(guān)心錯(cuò)誤檢測,中間環(huán)節(jié)只需要拋出異常是不是會(huì)好很多呢?方式二:就是通過調(diào)用堆棧向后搜索找到任何有興趣處理特定異常的方法


15.png


中間環(huán)節(jié)不需要關(guān)注異常的發(fā)生,只有關(guān)心異常的方法才會(huì)捕獲異常進(jìn)行相應(yīng)的處理。

3.好處三分組和區(qū)分錯(cuò)誤類型

因?yàn)槌绦蛑袙伋龅乃挟惓6际菍ο螅援惓5姆纸M或分類是類層次結(jié)構(gòu)的自然結(jié)果。Java 平臺(tái)中的一組相關(guān)異常類的一個(gè)例子是在 java.io- 及其 IOException 后代中定義的異常類。IOException 是最通用的,表示執(zhí)行 I / O 時(shí)可能發(fā)生的任何類型的錯(cuò)誤。其后代代表更具體的錯(cuò)誤。例如 FileNotFoundException 意味著文件不在磁盤上未找到

一種方法可以編寫可以處理非常特定異常的特定處理程序。FileNotFoundException 類有沒有后代, 所以下面處理器只能處理一種類型的異常。


16.png


一個(gè)方法也可以用更通用的處理器捕獲處理具體的異常。例如,為了捕獲所有的I/O異常,不管具體的類型是什么,只要給異常處理器指定一個(gè)IOException參數(shù)就行。


17.png


這個(gè)處理器可以捕獲所有的I/O異常,包括FileNotFoundException,EOFException等等。你可以通過查詢傳給異常處理器的參數(shù),發(fā)現(xiàn)錯(cuò)誤發(fā)生的細(xì)節(jié)。例如,用下面的代碼打印堆棧跟蹤信息:


18.png


在大多數(shù)情況下,你希望異常處理器越具體越好。理由是在你決定最佳的恢復(fù)策略之前,你首先要知道錯(cuò)誤的類型。事實(shí)上,如果不捕獲具體的錯(cuò)誤,這個(gè)處理器就必須要容納任何可能性。太通用的異常處理器可能會(huì)讓代碼更容易出錯(cuò),因?yàn)樗鼈儠?huì)捕獲和處理程序員意料之外的異常,這樣就超出處理器的能力范圍了。

三、J2EE核心語言中的異常

Java把異常當(dāng)做是破壞正常流程的一個(gè)事件,當(dāng)事件發(fā)生后,就會(huì)觸發(fā)處理機(jī)制。

Java有一套獨(dú)立的異常處理機(jī)制,在遇到異常時(shí),方法并不返回任何值(返回值屬于正常流程),而是拋出一個(gè)封裝了錯(cuò)誤信息的對象。下圖是Java異常處理機(jī)制類層級結(jié)構(gòu)圖:


2.webp.jpg


在 Java 中,所有的異常都有一個(gè)共同的祖先 Throwable(可拋出)。Throwable 指定代碼中可用異常傳播機(jī)制通過 Java 應(yīng)用程序傳輸?shù)娜魏螁栴}的共性。Throwable:有兩個(gè)重要的子類:*Exception(異常)和 Error(錯(cuò)誤)*,二者都是 Java 異常處理的重要子類,各自都包含大量子類。Error(錯(cuò)誤):是程序無法處理的錯(cuò)誤,表示運(yùn)行應(yīng)用程序中較嚴(yán)重問題。大多數(shù)錯(cuò)誤與代碼編寫者執(zhí)行的操作無關(guān),而表示代碼運(yùn)行時(shí) JVM(Java 虛擬機(jī))出現(xiàn)的問題。例如,Java虛擬機(jī)運(yùn)行錯(cuò)誤(Virtual MachineError),當(dāng) JVM 不再有繼續(xù)執(zhí)行操作所需的內(nèi)存資源時(shí),將出現(xiàn) OutOfMemoryError。這些異常發(fā)生時(shí),Java虛擬機(jī)(JVM)一般會(huì)選擇線程終止。這些錯(cuò)誤表示故障發(fā)生于虛擬機(jī)自身、或者發(fā)生在虛擬機(jī)試圖執(zhí)行應(yīng)用時(shí),如Java虛擬機(jī)運(yùn)行錯(cuò)誤(Virtual MachineError)、類定義錯(cuò)誤(NoClassDefFoundError)等。這些錯(cuò)誤是不可查的,因?yàn)樗鼈冊趹?yīng)用程序的控制和處理能力之 外,而且絕大多數(shù)是程序運(yùn)行時(shí)不允許出現(xiàn)的狀況。對于設(shè)計(jì)合理的應(yīng)用程序來說,即使確實(shí)發(fā)生了錯(cuò)誤,本質(zhì)上也不應(yīng)該試圖去處理它所引起的異常狀況。在 Java中,錯(cuò)誤通過Error的子類描述。

Exception(異常):是程序本身可以處理的異常。Exception 類有一個(gè)重要的子類 RuntimeException。RuntimeException 類及其子類表示“JVM 常用操作”引發(fā)的錯(cuò)誤。例如,若試圖使用空值對象引用、除數(shù)為零或數(shù)組越界,則分別引發(fā)運(yùn)行時(shí)異常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。

通常,Java的異常(包括Exception和Error)分為可查的異常(checked exceptions)和不可查的異常(unchecked exceptions)。

運(yùn)行時(shí)異常:都是RuntimeException類及其子類異常,如NullPointerException(空指針異常)、IndexOutOfBoundsException(下標(biāo)越界異常)等,這些異常是不檢查異常,程序中可以選擇捕獲處理,也可以不處理。這些異常一般是由程序邏輯錯(cuò)誤引起的,程序應(yīng)該從邏輯角度盡可能避免這類異常的發(fā)生。運(yùn)行時(shí)異常的特點(diǎn)是Java編譯器不會(huì)檢查它,也就是說,當(dāng)程序中可能出現(xiàn)這類異常,即使沒有用try-catch語句捕獲它,也沒有用throws子句聲明拋出它,也會(huì)編譯通過。

非運(yùn)行時(shí)異常 (編譯異常):是RuntimeException以外的異常,類型上都屬于Exception類及其子類。從程序語法角度講是必須進(jìn)行處理的異常,如果不處理,程序就不能編譯通過。如IOException、SQLException等以及用戶自定義的Exception異常,一般情況下不自定義檢查異常。

JVM字節(jié)碼分析異常處理機(jī)制


3.webp.jpg


 Java異常處理的一般性建議

1.try-catch-finally 規(guī)則

(1)必須在 try 之后添加 catch 或 finally 塊。try 塊后可同時(shí)接 catch 和 finally 塊,但至少有一個(gè)塊。 

(2)必須遵循塊順序:若代碼同時(shí)使用 catch 和 finally 塊,則必須將 catch 塊放在 try 塊之后。 

(3)catch 塊與相應(yīng)的異常類的類型相關(guān)。 

(4)一個(gè) try 塊可能有多個(gè) catch 塊。若如此,則執(zhí)行第一個(gè)匹配塊。即Java虛擬機(jī)會(huì)把實(shí)際拋出的異常對象依次和各個(gè)catch代碼塊聲明的異常類型匹配,如果異常對象為某個(gè)異常類型或其子類的實(shí)例,就執(zhí)行這個(gè)catch代碼塊,不會(huì)再執(zhí)行其他的 catch代碼塊 

(5)可嵌套 try-catch-finally 結(jié)構(gòu)。

(6)在 try-catch-finally 結(jié)構(gòu)中,可重新拋出異常。 

(7)除了下列情況,總將執(zhí)行 finally 做為結(jié)束:JVM 過早終止(調(diào)用 System.exit(int));在 finally 塊中拋出一個(gè)未處理的異常;計(jì)算機(jī)斷電、失火、或遭遇病毒攻擊。

2.Throws拋出異常的規(guī)則

如果是不可查異常(unchecked exception),即Error、RuntimeException或它們的子類,那么可以不使用throws關(guān)鍵字來聲明要拋出的異常,編譯仍能順利通過,但在運(yùn)行時(shí)會(huì)被系統(tǒng)拋出。 

必須聲明方法可拋出的任何可查異常(checked exception)。即如果一個(gè)方法可能出現(xiàn)受可查異常,要么用try-catch語句捕獲,要么用throws子句聲明將它拋出,否則會(huì)導(dǎo)致編譯錯(cuò)誤 

僅當(dāng)拋出了異常,該方法的調(diào)用者才必須處理或者重新拋出該異常。當(dāng)方法的調(diào)用者無力處理該異常的時(shí)候,應(yīng)該繼續(xù)拋出,而不是囫圇吞棗。 

調(diào)用方法必須遵循任何可查異常的處理和聲明規(guī)則。若覆蓋一個(gè)方法,則不能聲明與覆蓋方法不同的異常。聲明的任何異常必須是被覆蓋方法所聲明異常的同類或子類。

四、異常處理和設(shè)計(jì)

下面介紹異常處理和設(shè)計(jì)注意的一些點(diǎn):

1.使用異常,而不使用返回碼

關(guān)于這一點(diǎn),在上面『異常的好處』有解釋。理解了這一點(diǎn),程序員們才會(huì)想要使用Java異常處理機(jī)制。

2.利用運(yùn)行時(shí)異常設(shè)定方法使用規(guī)則

很常見的例子就是,某個(gè)方法的參數(shù)不能為空。在實(shí)踐中,很多程序員的處理方式是,當(dāng)傳入的這個(gè)參數(shù)為空的時(shí)候,就返回一個(gè)特殊值(最常見的就是返回一個(gè)null,讓用戶方法決定怎么辦)。還有的處理方式是,自己給一個(gè)默認(rèn)值去兼容這種不合法參數(shù),自己決定怎么辦。這兩種實(shí)踐都是不好的。

對于第一種處理方式,返回值是用來處理正常流程的,如果用來處理異常流程,就會(huì)讓用戶方法的正常流程變復(fù)雜。一次調(diào)用可能不明顯,當(dāng)有多個(gè)連續(xù)調(diào)用就會(huì)變得很復(fù)雜了。對于第二種處理方式,看起來很強(qiáng)大,因?yàn)椤叭蒎e(cuò)”能力看起來很強(qiáng),有些程序員甚至可能會(huì)為此沾沾自喜。但是它也一樣讓正常流程變復(fù)雜了,這不是最糟糕的,最糟糕的是,你不知道下一次用戶會(huì)出什么鬼點(diǎn)子,傳個(gè)你現(xiàn)有處理代碼處理不了的東西進(jìn)來。這樣你又得加代碼,繼續(xù)變復(fù)雜……BUG就是這樣產(chǎn)生的。

好的實(shí)踐方式就是,設(shè)定方法的使用規(guī)則,遇到不合法的使用方式時(shí),立刻拋出一個(gè)運(yùn)行時(shí)異常。這樣既不會(huì)讓主流程代碼變復(fù)雜,也不會(huì)制造不必要的BUG。為什么是運(yùn)行時(shí)異常而不是檢查異常呢?這是為了強(qiáng)迫用戶修改代碼或者改正使用方式——這屬于用戶的使用錯(cuò)誤。

3.消除運(yùn)行時(shí)異常

當(dāng)你的程序發(fā)生運(yùn)行時(shí)異常,通常都是因?yàn)槟闶褂脛e人的方法的方式不正確(如果設(shè)計(jì)這個(gè)異常的人設(shè)計(jì)錯(cuò)誤,就另當(dāng)別論。比如設(shè)計(jì)者捕獲一個(gè)檢查異常,然后在處理器拋出一個(gè)運(yùn)行時(shí)異常給用戶。如果遇上這樣的供應(yīng)商,還是棄用吧)。所以,一般都是采取修改代碼的方式,而不是新增一個(gè)異常流程。

4.正確處理檢查異常

處理檢查異常的時(shí)候,處理器一定要做到下面的要求才算合格:

(1)返回到一種安全狀態(tài),并能夠讓用戶執(zhí)行一些其他的命令;

(2)允許用戶保存所有操作的結(jié)果,并以適當(dāng)?shù)姆绞浇K止程序。

不好的實(shí)踐案例一:因?yàn)橛械漠惓0l(fā)生的概率很小,有些程序員就會(huì)寫出下面的代碼:

public Image loadImage(String s) {

     try {

          code...

     } catch (Exception e)

     {}

     code2...

}

catch代碼塊里面什么都不寫!或者只在里面打一個(gè)log。這樣既不會(huì)傳遞到上層方法,又不會(huì)報(bào)編譯錯(cuò)誤,還不用動(dòng)腦筋……

不好的實(shí)踐案例二:捕獲一個(gè)檢查異常,什么都不做(或只打一個(gè)log),然后拋出一個(gè)運(yùn)行時(shí)異常:

public Image loadImage(String s) {

     try {

          code...

     } catch (Exception e){

          throw new RuntimeExcepiton();

     }

}

這樣也不會(huì)讓上層方法感覺到這個(gè)異常的存在,也不會(huì)報(bào)編譯錯(cuò)誤了,也不用動(dòng)什么腦筋……

在案例一中,一旦出現(xiàn)了異常,try代碼塊里的代碼沒執(zhí)行完,用戶要求做的事情沒做完,卻又沒有任何反饋或者得到一個(gè)錯(cuò)誤反饋。

在案例二中,一旦出現(xiàn)了異常,try代碼塊里的代碼沒執(zhí)行完,雖然把運(yùn)行時(shí)異常拋給用戶了,用戶也不會(huì)去處理這個(gè)異常,又沒有辦法通過改變使用方式消除異常,直接讓用戶代碼崩潰掉。

對于檢查異常,好的實(shí)踐方式是:

(1)讓可以處理這個(gè)異常的方法去處理。衡量的標(biāo)準(zhǔn)就是在你這個(gè)方法寫一個(gè)處理器,這個(gè)處理器能不能做到本節(jié)開頭的那兩個(gè)要求,如果不能,就往上拋。如果你不能知道所有用戶的所有需求,你通常就做不到那兩個(gè)要求。

(2)有必要的時(shí)候可以通過鏈?zhǔn)疆惓0b一下,再拋出。

(3)最終的處理器一定要做到本節(jié)開頭的那兩個(gè)要求。

5.使主流程代碼保持整潔

一個(gè)try代碼塊后面可以跟多個(gè)catch代碼塊,這就讓一些可能會(huì)發(fā)生不同異常的代碼可以寫在一塊,讓代碼看起來很清晰。相反,在一個(gè)方法里寫多個(gè)try-catch,或者寫嵌套的try-catch,就會(huì)讓主流程代碼變得很混亂。

6.使用try-with-resources

try-with-resources語句比起普通的try語句,干凈整潔的多。而且最終拋出的異常是正常流程中拋出的異常。

7.盡量處理最具體的異常

盡量使用最具體的異常類作為處理器匹配的類型。這樣處理器就不用兼顧很多種情形,不易出錯(cuò)。從Java7開始,一個(gè)處理器可以處理多種異常類型。

注意:同一個(gè)try語句中,比較具體的異常的catch代碼塊應(yīng)寫在前面,比較通用的異常的catch代碼塊應(yīng)寫在后面。

8.設(shè)計(jì)自己的異常類型要遵循的原則

當(dāng)你是一個(gè)模塊開發(fā)者,你就很有必要設(shè)計(jì)一組或多組自己的異常類型。一般情況下,要遵守如下原則:

(1)確定什么場景下,需要?jiǎng)?chuàng)建自己的異常類型。

(2)為你的接口方法的使用規(guī)則創(chuàng)建一組運(yùn)行時(shí)異常。

(3)封裝別人的檢查異常的時(shí)候,一定也要用檢查異常。這樣異常才能傳遞給上層方法處理。

(4)設(shè)計(jì)一組有層次結(jié)構(gòu)的異常,而不是設(shè)計(jì)一堆零零散散的異常。

(5)區(qū)分清楚異常發(fā)生的原因,然后決定你的異常是檢查異常還是運(yùn)行時(shí)異常。

(6)模塊內(nèi)部不需要處理自己定義的異常。

五、總結(jié)

Java異常處理機(jī)制的目的至少有三個(gè):一是歸類處理不同的異常,二是提供足夠的信息方便調(diào)試,三是讓主流程代碼保持整潔。

最后貼一張異常梳理的腦圖


4.webp.jpg


提交成功!非常感謝您的反饋,我們會(huì)繼續(xù)努力做到更好!

這條文檔是否有幫助解決問題?

非常抱歉未能幫助到您。為了給您提供更好的服務(wù),我們很需要您進(jìn)一步的反饋信息:

在文檔使用中是否遇到以下問題: