3 回答

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

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

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