2012-11-22 150 views
6

我在C#入門書中讀到,如果你不知道如何處理它,你不應該發現異常。在使用Java進行編程時,考慮到這一點建議,我有時會發現我不知道如何處理異常,但我不得不趕上它或「滲透」以避免編譯錯誤。我寧願不要在調用樹中使用throws條款,所以我經常採用將「異常」「轉換」爲RuntimeException,如下所示。將throws子句添加到許多方法中,對於沒有真正「處理」(正確處理)的異常似乎冗長和分散注意力。下面是不好的風格,如果是的話,什麼是更好的方式來處理這個問題?處理災難性例外

try { 
    thread.join(); 
} 
catch (InterruptedException e) { 
     Console.printwriter.format("%s\n", e.printStackTrace()); 
    throw new RuntimeException(); 
} 

編輯:除了雜亂,有與滲透例外另一個問題:後代碼修改你可能有一些不必要的throws條文結束。我知道清除它們的唯一方法是通過試驗和錯誤:刪除它們,看看編譯器是否抱怨。顯然,如果你想保持代碼清潔,這是很煩人的。

+0

更好的方法來處理它是以不必經常拋出異常的方式編寫代碼。 – lifetimes

+0

同意。我通常不會聲明許多新定義的例外。我主要關心第三方和Java異常。 – H2ONaCl

+0

@ user1394965是的,你的代碼不應該「不斷地」拋出異常。但是,這與例外是否可能是非常不同的問題。涉及IO操作或阻塞方法的任何事情都可能被無法避免的異常處理所困擾。 –

回答

5

在Java中,在checked和unchecked exceptions之間的劃分是somewhat controversial

如果你控制接口,添加一個throws子句到簽名通常是最好的方法。

如果您處於一種無法處理異常但不允許由於檢查的異常簽名而使其冒泡的情況,那麼將該異常包裝爲可以重新拋出的異常(通常是RuntimeException)是常見的做法。

在許多情況下,您希望使用另一個檢查過的異常,例如IOException或SQLException。但這並不總是一種選擇。

但在你的榜樣,包括原始異常的「原因」:

throw new RuntimeException(e); 

這也可以消除對記錄的需要(因爲這也可以被推遲到人誰可以處理異常,並且所有信息仍然存在)。

1

如果你不知道如何處理異常,你不應該抓住它。因此,你的方法現在會拋出一個異常,所以它應該有一個throws子句,如果它不是運行時異常。他們沒有錯。

+0

@broiyan是的,我正在回答你的問題,你正在處理一個正常的例外。 – Pablo

1

我喜歡Joshua Bloch的Effective Java 2nd edition的建議 - 拋出適合於抽象(Item 61)的異常。

也就是說,當面臨着一系列的例外,你希望「滲透」出你的方法,考慮是否異常應重新包裹的東西,使更多的語義適合您的方法。

這種方法往往具有幾個較低級別的異常組合成單個更高級別的異常的令人愉悅的副作用。

+0

這是一個好主意。 – H2ONaCl

+0

這是在簡化拋出異常的好處與發明數百個自定義異常之間取得平衡的行爲,這些自定義異常使您的代碼庫膨脹。 –

1

良好的編程習慣告訴你應該隱藏調用者的對象的內部狀態,至​​少對我來說,這也包括例外。您應該瞭解該異常對您的意義,並返回給您的類的invokers一個表示該含義的Exception。

如果框架已經提供了與意義的異常,例如拋出:IllegalArgumentException,您應該實例化一個新的對象,給它發生了什麼很好的描述字符串和封裝內容時發生異常,沿着新拋出:IllegalArgumentException東西線(「論據X因......而無效」,e); 如果框架對於您的問題沒有很好的描述性例外,則應該創建自己的一組例外。我通常爲該項目/包創建一個通用異常(這將擴展Exception或RuntimeException)並從中衍生出異常。 例如,我最近創建了一個通用存儲庫項目,以便在我們的服務和應用程序模塊中重用來訪問數據庫。由於我想從我用來訪問數據庫的東西中抽象出調用者,即使是來自異常,我也最終創建了一些異常來封裝JPA Hibernate異常。我沒有這裏的代碼,但它類似於:

// implementation package 
public abstract class GenericRepository<K, E extends<K>> implements IRepository<K, E>{ 

    // constructors 

    public final void add(E entity){ 
     // some code 

     try{ 
      // code that can throw exceptions 
     } catch (EntityExistsException e) { 
      // some code 
      throw new EntityAlreadyExistsException(e); 
     } catch(RuntimeException e) { 
      // some code 
      throw new GenericRepositoryException("An unexpected exception occurred while manipulating the database", e); 
     } 
    } 

    // some other code 

} 


// exception package 
public final class EntityAlreadyExistsException extends GenericRepositoryException{ 

    public static final String GENERICMESSAGE = "The entity already exists on the table"; 

    public EntityAlreadyExistsException(Throwable cause){ 
     super(GENERICMESSAGE, cause); 
    } 

    // other constructors 

}