摘要:指示該錯(cuò)誤是否嚴(yán)重,此屬性會(huì)在該異常根據(jù)錯(cuò)誤的上下文遍歷堆棧時(shí)進(jìn)行更新,嚴(yán)重性會(huì)指示異常捕獲代碼是應(yīng)該停止程序還是該繼續(xù)處理。引發(fā)異常在檢測(cè)到錯(cuò)誤并無(wú)法從中恢復(fù)時(shí),異常將向上傳播到調(diào)用堆棧,直到到達(dá)處理它的某個(gè)塊。
翻譯:瘋狂的技術(shù)宅
原文標(biāo)題:Exception handling strategy
原文鏈接:http://programmergate.com/exc...
本文首發(fā)微信公眾號(hào):充實(shí)的腦洞
在本文中,我們介紹了在OOP應(yīng)用中處理異常的常見(jiàn)策略,這些策略符合最佳的異常處理技術(shù),可以在任何應(yīng)用中使用。
1. 概述下圖提供了策略概述,它展示了從檢測(cè)階段到處理階段的異常處理流程。該圖需要從下往上進(jìn)行閱讀:
Error detection: 在策略的底部是錯(cuò)誤檢測(cè),這是發(fā)生異常的地方,它要么由程序進(jìn)行檢測(cè),要么由一些外部調(diào)用引發(fā)。
Local exception handling: 在第二級(jí)是本地異常處理,檢測(cè)錯(cuò)誤的類嘗試在本地處理異常,例如:將請(qǐng)求發(fā)送到備份服務(wù)器,或等待X秒后再次嘗試等...如果異常無(wú)法恢復(fù),則將其傳播到較高級(jí)別。
Propagate exception to higher levels: 當(dāng)本地錯(cuò)誤處理不起作用時(shí),該類收集診斷信息,再現(xiàn)和報(bào)告錯(cuò)誤所需的所有信息,然后將該異常傳到棧中。 如果檢測(cè)到的異常不是低級(jí)別依賴(取決于低級(jí)別實(shí)現(xiàn)),那么它將被拋出,否則將被轉(zhuǎn)換為自定義異常,以實(shí)現(xiàn)組件之間的解耦。
Keep propagating if nothing to do with the exception: 較高級(jí)別的類將會(huì)繼續(xù)將異常傳到棧中, 只要它們與異常無(wú)關(guān)。同時(shí)關(guān)閉在傳遞路徑的所有資源(例如文件、網(wǎng)絡(luò)連接、釋放分配的緩沖區(qū)等),并添加相關(guān)的上下文信息, 這將有助于確定錯(cuò)誤的原因和嚴(yán)重性。
Handle exception:在這個(gè)階段,異常會(huì)到達(dá)一個(gè)負(fù)責(zé)處理它的類,異常所攜帶的所有錯(cuò)誤信息都記錄在此,并且根據(jù)異常的嚴(yán)重性,該類可以處理異常或者結(jié)束程序。
2. 自定義異常模板實(shí)現(xiàn)異常處理策略時(shí)要做的第一件事就是,為程序的每個(gè)組件創(chuàng)建自定義異常,自定義異常如下所示:
public class ComponentException extends Exception { private static final long serialVersionUID = 1L; private int errorCode; private String errorDescription; private boolean isSevere; public ComponentException() { super(); } public ComponentException(Exception ex) { super(ex); } public int getErrorCode() { return errorCode; } public void setErrorCode(int errorCode) { this.errorCode = errorCode; } public String getErrorDescription() { return errorDescription; } public void setErrorDescription(String errorDescription) { this.errorDescription = errorDescription; } public boolean isSevere() { return isSevere; } public void setSevere(boolean isSevere) { this.isSevere = isSevere; } }
以下描述了ComponentException類的屬性:
errorCode:識(shí)別此錯(cuò)誤的唯一代碼,errorCode告訴我們那里出錯(cuò)了,程序的所有錯(cuò)誤代碼應(yīng)在靜態(tài)類中進(jìn)行預(yù)定義。該屬性指示異常捕獲代碼應(yīng)該怎樣處理這個(gè)錯(cuò)誤。
errorDescription: 對(duì)錯(cuò)誤的描述,描述了用戶、程序操作人員和可能的程序開(kāi)發(fā)人員所需的一切必要的細(xì)節(jié),可以使他們了解到底發(fā)生了什么錯(cuò)誤。
isSevere: 指示該錯(cuò)誤是否嚴(yán)重,此屬性會(huì)在該異常根據(jù)錯(cuò)誤的上下文遍歷堆棧時(shí)進(jìn)行更新,嚴(yán)重性會(huì)指示異常捕獲代碼是應(yīng)該停止程序還是該繼續(xù)處理。
3.引發(fā)異常在檢測(cè)到錯(cuò)誤并無(wú)法從中恢復(fù)時(shí),異常將向上傳播到調(diào)用堆棧,直到到達(dá)處理它的某個(gè) try-catch塊。該異常可以按原樣傳遞,也可轉(zhuǎn)換為自定義異常。
3.1 拋出異常如果異常不依賴于定期更改的低級(jí)實(shí)現(xiàn)或動(dòng)態(tài)實(shí)現(xiàn),那么你只需關(guān)閉打開(kāi)的資源,并把異常積蓄傳到調(diào)用棧而不去捕獲它。下面是一個(gè)例子:
public void doSomething() throws SomeException { try{ doSomethingThatCanThrowException(); } finally { //close the opened resources } }3.2 拋出自定義異常
當(dāng)捕獲的異常取決于低級(jí)別或動(dòng)態(tài)實(shí)現(xiàn)時(shí),它會(huì)被轉(zhuǎn)換為一個(gè)特定的異常,然后重新啟動(dòng)調(diào)用堆棧。 下面是一個(gè)例子:
public Student readStudent(String id) throws SomeException { try { // Some code which reads a student from oracle database } catch(SQLException ex) { DataAccessException dataAccessException = new DataAccessException(ex); dataAccessException.setErrorCode(101); // we assume this code denotes student not found dataAccessException.setErrorMessage("An error occurred while reading " + "student with id: " + id + " from database"); dataAccessException.setSeverity(false); throw dataAccessException; } }
只要它還沒(méi)有到達(dá)能夠處理它的類,異常就會(huì)繼續(xù)傳播。
P.S:強(qiáng)烈建議在異常傳播到堆棧時(shí)更新異常的嚴(yán)重性,無(wú)論是異常被繼續(xù)拋出,還是轉(zhuǎn)換為自定義異常。
4. 捕獲異常在程序中,你需要捕獲并響應(yīng)來(lái)拋出異常,通常你需要在調(diào)用層次的頂部執(zhí)行此操作。
捕獲異常時(shí)首先要做的是記錄它,通常我更喜歡使用printStackTrace(),之后的處理過(guò)程取決于異常的嚴(yán)重性:
如果嚴(yán)重,則通知開(kāi)發(fā)人員和程序操作人員,并且結(jié)束程序。
如果不嚴(yán)重,則根據(jù)錯(cuò)誤代碼完成處理。通常有兩種可能性,可以靜默地從異常中恢復(fù),或者通知最終用戶并停止當(dāng)前進(jìn)程。
下面是一個(gè)例子:
try{ startTheWholeThing(); } catch(MyAppException e) { e.printStackTrace(); if(e.isSevere()) { notifyNonUsers(e); // Halt the system gracefully } else { if(e.getErrorCode() == 100) { // do some silent recovery logic } else { notifyUsers(e); } } }
以上是我在程序中處理異常時(shí)所遵循的策略,希望你能喜歡。
關(guān)注微信公眾號(hào):充實(shí)的腦洞, 一個(gè)技術(shù)宅的保留地 | |
---|---|
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/67719.html
摘要:近日,在上列舉了開(kāi)發(fā)中常見(jiàn)的個(gè)錯(cuò)誤,與君共免。在多線程中并發(fā)修改集合內(nèi)容是非常常見(jiàn)的,因此需要使用并發(fā)編程中常用的方法進(jìn)行處理,例如同步鎖對(duì)于并發(fā)修改采用特殊的集合等等。在單線程和多線程情況下解決這個(gè)問(wèn)題有微小的差別。 在編程時(shí),開(kāi)發(fā)者經(jīng)常會(huì)遭遇各式各樣莫名錯(cuò)誤。近日,Sushil Das 在 Geek On Java上列舉了 Java 開(kāi)發(fā)中常見(jiàn)的 5 個(gè)錯(cuò)誤,與君共「免」。 原文...
摘要:生產(chǎn)者消費(fèi)者問(wèn)題是一個(gè)典型的多進(jìn)程同步問(wèn)題。生產(chǎn)者線程開(kāi)始產(chǎn)生新的元素并將它們存儲(chǔ)在緩沖區(qū)。否則,生產(chǎn)者線程將會(huì)在緩沖區(qū)創(chuàng)建一個(gè)新元素然后通知消費(fèi)者。我們建立一個(gè)線程池,它將收到兩個(gè)任務(wù),生產(chǎn)者和消費(fèi)者的任務(wù)。 原文鏈接:https://dzone.com/articles/th... 作者:Ioan Tinca 譯者:liumapp 想要了解更多關(guān)于Java生產(chǎn)者消費(fèi)者問(wèn)題的演變嗎?...
摘要:能否聲明一個(gè)內(nèi)容為空的接口可以。能否將接口聲明為不允許,這樣做會(huì)導(dǎo)致編譯錯(cuò)誤。當(dāng)異常沒(méi)有被捕獲時(shí),會(huì)發(fā)生什么當(dāng)前線程所在的線程組會(huì)執(zhí)行一個(gè)叫的方法,最后程序會(huì)異常退出。非靜態(tài)內(nèi)部類可以使用哪些修飾符非靜態(tài)內(nèi)部類可以使用或修飾符。 原文地址 http://www.instanceofjava.com/2014/12/core-java-interview-questions.html 1...
摘要:我們應(yīng)該考慮使用字符串常量調(diào)用方法來(lái)代替使用對(duì)象調(diào)用該方法。然而如果我們通過(guò)字符串常量來(lái)調(diào)用方法,執(zhí)行流程會(huì)正常進(jìn)行檢查方法的參數(shù)在執(zhí)行方法的方法體之前,務(wù)必對(duì)方法的參數(shù)進(jìn)行值檢查。 原文地址作者 Sotirios-Efstathios (Stathis) Maneas譯者 smallcloverThanks for your watching! java.lang.NullPoine...
摘要:每個(gè)消費(fèi)者會(huì)得到平均數(shù)量的。為了確保不會(huì)丟失,采用確認(rèn)機(jī)制。如果中斷退出了關(guān)閉了,關(guān)閉了,或是連接丟失了而沒(méi)有發(fā)送,會(huì)認(rèn)為該消息沒(méi)有完整的執(zhí)行,會(huì)將該消息重新入隊(duì)。該消息會(huì)被發(fā)送給其他的。當(dāng)消費(fèi)者中斷退出,會(huì)重新分派。 Work模式 原文地址showImg(https://segmentfault.com/img/bVbqlXr?w=694&h=252); 在第一章中,我們寫(xiě)了通過(guò)一個(gè)...
閱讀 582·2021-11-22 14:45
閱讀 3070·2021-10-15 09:41
閱讀 1555·2021-10-11 10:58
閱讀 2797·2021-09-04 16:45
閱讀 2606·2021-09-03 10:45
閱讀 3238·2019-08-30 15:53
閱讀 1221·2019-08-29 12:28
閱讀 2133·2019-08-29 12:14