3 回答

TA貢獻(xiàn)1808條經(jīng)驗 獲得超4個贊
對我來說,想要捕獲異常并將它們轉(zhuǎn)換為錯誤代碼似乎很奇怪。為什么在后者是Java和C#中的默認(rèn)值時,您認(rèn)為調(diào)用者更喜歡錯誤代碼而不是異常?
至于你的問題:
您應(yīng)該只捕獲實際可以處理的異常。在大多數(shù)情況下,捕獲異常并不是正確的做法。有一些例外(例如,線程之間的日志記錄和編組異常),但即使對于這些情況,通常也應(yīng)該重新拋出異常。
你的代碼中絕對不應(yīng)該有很多try / catch語句。同樣,我們的想法是只捕獲您可以處理的異常。您可以包含一個最頂層的異常處理程序,將任何未處理的異常轉(zhuǎn)換為對最終用戶有用的東西,但是否則您不應(yīng)該嘗試捕獲每個可能位置的每個異常。

TA貢獻(xiàn)1836條經(jīng)驗 獲得超4個贊
這取決于應(yīng)用和情況。如果你構(gòu)建一個庫組件,你應(yīng)該冒出異常,盡管它們應(yīng)該被包裝成與你的組件一起上下文。例如,如果您構(gòu)建一個Xml數(shù)據(jù)庫并假設(shè)您正在使用文件系統(tǒng)來存儲數(shù)據(jù),并且您正在使用文件系統(tǒng)權(quán)限來保護(hù)數(shù)據(jù)。您不希望冒出一個FileIOAccessDenied異常,因為它會泄漏您的實現(xiàn)。相反,您將包裝異常并拋出AccessDenied錯誤。如果您將組件分發(fā)給第三方,則尤其如此。
至于是否可以吞下例外。這取決于你的系統(tǒng)。如果您的應(yīng)用程序可以處理故障情況,并且通知用戶失敗的原因沒有任何好處,那么請繼續(xù),盡管我強(qiáng)烈建議您記錄失敗。我總是覺得很難打電話來幫助解決問題并發(fā)現(xiàn)他們正在吞下異常(或者替換它并拋出新的異常而不設(shè)置內(nèi)部異常)。
一般來說,我使用以下規(guī)則:
在我的組件和庫中,如果我打算處理它或基于它做某些事情,我只會捕獲異常?;蛘?,如果我想在異常中提供其他上下文信息。
我在應(yīng)用程序入口點(diǎn)或盡可能高的級別使用常規(guī)try catch。如果異常到達(dá)此處,我只需記錄它并讓它失敗。理想情況下,異常永遠(yuǎn)不會到達(dá)此處
我發(fā)現(xiàn)以下代碼是一種氣味:
try{ //do something}catch(Exception){ throw;}
像這樣的代碼沒有任何意義,不應(yīng)該包括在內(nèi)。

TA貢獻(xiàn)1784條經(jīng)驗 獲得超8個贊
我想就這個主題推薦另一個好的來源。這是對C#和Java,Anders Hejlsberg和James Gosling的發(fā)明者的訪談,分別是關(guān)于Java的Checked Exception的主題。
頁面底部還有很多資源。
我傾向于同意Anders Hejlsberg和你的看法,大多數(shù)來電者只關(guān)心操作是否成功。
Bill Venners:您提到了關(guān)于已檢查異常的可擴(kuò)展性和版本控制問題。你能澄清這兩個問題的含義嗎?
Anders Hejlsberg:讓我們從版本開始,因為問題很容易在那里看到。假設(shè)我創(chuàng)建了一個聲明它拋出異常A,B和C的方法foo。在foo的第二個版本中,我想添加一些功能,現(xiàn)在foo可能會拋出異常D.這對我來說是一個徹底的改變。將D添加到該方法的throws子句中,因為該方法的現(xiàn)有調(diào)用者幾乎肯定不會處理該異常。
在新版本中向throws子句添加新異常會破壞客戶端代碼。這就像在界面中添加方法一樣。在發(fā)布接口之后,它實際上是不可變的,因為它的任何實現(xiàn)都可能具有您要在下一個版本中添加的方法。所以你必須創(chuàng)建一個新的界面。與異常類似,您可能必須創(chuàng)建一個名為foo2的全新方法,該方法會拋出更多異常,或者您必須在新foo中捕獲異常D,并將D轉(zhuǎn)換為A,B或C.
Bill Venners:但是你不是在這種情況下破壞他們的代碼,即使是在沒有檢查異常的語言中嗎?如果foo的新版本將拋出一個客戶應(yīng)該考慮處理的新異常,那么他們的代碼是不是因為他們在編寫代碼時沒有預(yù)料到異常這一事實?
Anders Hejlsberg:不,因為在很多情況下,人們并不關(guān)心。他們不會處理任何這些例外情況。它們的消息循環(huán)周圍有一個底層異常處理程序。那個處理程序只是打開一個對話框,說明出了什么問題并繼續(xù)。程序員通過在任何地方編寫try finally來保護(hù)他們的代碼,因此如果發(fā)生異常他們將正確退出,但他們實際上并不感興趣處理異常。
throws子句,至少它在Java中的實現(xiàn)方式,并不一定會強(qiáng)制您處理異常,但如果您不處理它們,它會強(qiáng)制您確切地確認(rèn)哪些異常可能會通過。它要求您捕獲聲明的異?;?qū)⑺鼈兎旁谀约旱膖hrows子句中。為了解決這個問題,人們做了荒謬的事情。例如,他們用“拋出異常”來裝飾每個方法。這完全打敗了這個功能,你只是讓程序員寫了更多的gobbledy gunk。這對任何人都沒有幫助。
編輯:添加了有關(guān)轉(zhuǎn)換的更多詳細(xì)信息
添加回答
舉報