2008-10-26 90 views

回答

25

我認爲你需要問自己一個非常不同的問題「創建一個新的例外給我或開發者誰使用我的代碼?「真的,它給你或其他人的唯一好處是能夠處理異常。這似乎是一個明顯的答案,但事實並非如此。您應該只處理可以合理恢復的異常。如果你拋出的異常是一個真正致命的錯誤,爲什麼會給開發人員一個錯誤處理它的機會?

更深入的討論:Custom exceptions: When should you create them?

+3

如果您不想混淆用戶,也可以創建一個。java.lang.Exception可能意味着一些可能出錯的事情AppFileNotFound(sFilePath) - 有助於減少在布什附近的跳動... – Gishu 2008-10-26 05:36:32

7

當我想從其他人的區別對待我的異常。如果我想抓住我的並宣傳其他人的話,或者如果我想抓住別人的並傳播我的想法,或者如果我想抓住兩者但以不同的方式對待他們,那麼我會爲我的例外定義一個單獨的類。如果我想把它們都對待,無論是通過傳播還是通過捕獲兩者(並以捕捉到的異常來做同樣的事情),我將使用標準類。

-1

在大多數情況下,創建您自己的異常類是沒有意義的。

新手程序員有一種傾向,即創建自己的異常類,以便他們可以使用更能表明錯誤類型的名稱。所以你會發現像FTPInitializationException,DAOFactoryException等類,即使這些異常的處理方式與標準異常不同。這顯然是應該避免的反模式。

+0

建議程序員拋出java.lang.Exception遠比拋出自己的類比擴展java.lang.Exception;有很多異常會導致j.l.Exception不應被捕獲。 – janm 2008-10-26 13:49:42

+0

Downvoted。人們可以直接拋出「RuntimeException」而無需子類化,因爲調用者無法恢復。但是當你拋出「異常」時,你期望調用者能夠恢復。但是,如果你不給他們一個特定的子類,他們如何有足夠的上下文來恢復? – benjismith 2011-11-13 18:24:59

2

始終通過使用常見的異常類開始,然後當需要出現專門處理它時,請對其進行更改。

  1. 首次創建方法時,只需讓異常通過即可。

  2. 如果有必須處理的異常,那麼可以只是在throws中定義或者包裝到某個運行時異常或包裝自己的throws異常。在很多情況下我更喜歡運行時異常。應該避免定義投擲定義,直到從API的角度來看需要它。

  3. 後來,當某個需求似乎對某個調用者中的異常做特定的處理時,回來併爲其創建新的異常。

重點是在知道需要什麼之前避免做額外的工作。

+1

Exception類是特殊的; 「catch(Exception e)」會捕獲所有你可能不應該捕捉的東西。 – janm 2008-10-26 13:48:02

6

如果語言運行時或庫存在現有的異常,則使用它,否則創建自己的文檔,並將其記錄到文檔中,並且應該在99%的情況下工作。

11

原因一:

需要捕捉特定的東西。如果調用代碼需要處理特定的異常情況,則需要區分異常,並且Java將異常與不同類型區分開來,因此您需要編寫自己的異常。

基本上,如果有人寫:

catch(ExistingException e) { 
    if({condition}) { 
    { some stuff here} 
    } 
    else { 
    { different stuff here} 
    } 
} 

你可能想要寫一個特定的擴展; catch異常匹配比條件更清晰,恕我直言。

記住:你的新的異常可以 RuntimeException的

原因二的

一個子類:

API整合。如果你寫一個接口,你有幾個實現,這是可能的,他們將調用不同的API與拋出一大堆不同的非RuntimeExceptions的:

interface MyInterface { 
    void methodA(); 
} 

class MyImplA { 
    void methodA() throws SQLException { ... } 
} 

class MyImplB { 
    void methodA() throws IOException { ... } 
} 

你真的想MyInterface.methodA到拋出SQLException和IOException異常?也許那麼在自定義異常中包裝可能的異常是有意義的。這又可以是RuntimeException。或者甚至是RuntimeException本身...

0

當異常涉及API時,我會使用Java API中的異常。但是,如果出現一種特殊情況,這對我自己的API來說是獨一無二的,那麼我將爲它創建一個例外。例如,如果我有一個具有兩個屬性min和max的Range對象,並且不變量min < = max,那麼我將創建一個異常InvalidRangeException。

當我編寫代碼時,這有助於我知道是否因爲我違反了我自己的條件之一或來自Java API的某個東西而發生異常。

8

筆者認爲:

catch (Exception e) { 
    ... 
} 

...是應該避免的反模式。您可能希望在應用程序中的某處集中廣泛地捕獲,記錄錯誤並防止整個應用程序終止 - 但讓它們散落在無處不在的地方是很糟糕的。

爲什麼:

try { 
    if(myShape.isHidden()) { 
     throw new Exception(); 
    } 
    // More logic 
} catch (Exception e) { 
    MyApp.notify("Can't munge a hidden shape"); 
} 

所以,你試試這個,而且由於一個編碼錯誤,是MyShape的空。運行時試圖揭示myShape時引發NullPointerException。此代碼報告一個隱藏的形狀,當它應該報告一個空指針。

要麼你自己的例外,要麼在API中找到適當特殊的例外。這並不像擴展Exception或RuntimeException那樣繁重。

1

如果某個對象/類/方法有問題,我無法想象如何特別拋出java.lang.Exception。這太泛化了 - 如果你不打算創建自己的Exception類,在我看來,至少應該是API中更具體的Exception類型。

4

軟件捕捉含義。

拋出現有異常幾乎沒有理由:JVM已經爲您做了這件事。你的異常版本並不準確,拋出「異常」也沒有意義。

由於您編寫的解析算法,您可能有一個DataFormatException。然而,這很少見。

當您的程序遇到異常情況時,它對於您的程序幾乎總是唯一的。爲什麼迫使您將特殊情況融入現有的異常?如果它對你的程序來說是獨一無二的,那麼......好吧......它是獨一無二的。這樣命名。

但是,不要爲每個唯一的消息提供唯一的異常類。一個例外可以具有許多變體消息和支持細節。

翻譯爲Java的Python經驗法則是在包級別定義任何唯一的異常。 [在Python中,他們建議在「模塊」級別有例外,這種情況不能精確地轉化爲Java。]