在java中,我想記錄異常從一段代碼被拋出:的java:日誌拋出異常
try
{
doRiskyThing();
}
catch(Throwable t)
{
log.warn("too bad");
throw t;
}
的問題是,現在我的方法必須聲明它拋出的Throwable。另一方面,如果我在finally塊中記錄異常,我怎麼知道拋出了什麼異常(並且如果任何異常被拋出)。
在java中,我想記錄異常從一段代碼被拋出:的java:日誌拋出異常
try
{
doRiskyThing();
}
catch(Throwable t)
{
log.warn("too bad");
throw t;
}
的問題是,現在我的方法必須聲明它拋出的Throwable。另一方面,如果我在finally塊中記錄異常,我怎麼知道拋出了什麼異常(並且如果任何異常被拋出)。
您至少可以爲未檢查的異常和n個catch塊編寫捕獲異常。
try{
..
}catch(RuntimeException e){
log(e);
throw e;
}catch(ExceptionException ..){
log(e);
throw e;
}
這不會改變您的方法的簽名。捕捉錯誤是有點味道。那麼,記錄和拋出異常也是一種氣味。這將重複錯誤消息。
提前異常處理是從項目硬幣JDK 7
這似乎是登錄異常的錯誤地方。在拋出時將它記錄在doRiskyThing()中,或者將其記錄在應該被捕獲的地方。
這應該工作:
try
{
doRiskyThing();
}
catch(RuntimeException e)
{
log.warn("too bad");
throw e;
}
catch(Exception e)
{
log.warn("too bad");
throw new RuntimeException(e);
}
catch(Error e)
{
log.warn("too bad");
throw e;
}
但它的醜陋,我寧願有一個catch塊,在應用程序的頂層捕捉一切,並將其記錄,沒有再扔。無論如何,堆棧跟蹤可以讓您找出問題所在。
您可以記錄Throwable,並引發RuntimeException。
在Java中,您必須聲明您的方法本身可能拋出的任何異常,因爲它被視爲方法簽名的一部分....也就是說,除了RuntimeException之外,它避免了該規則。如果您願意,RuntimeException可以將Throwable的消息作爲其消息的一部分。然而
try
{
doRiskyThing();
}
catch(Throwable t)
{
log.warn("too bad, exception thrown: " + t.getMessage());
throw new RuntimeException("Throwable exception was thrown, message: " + t.getMessage());
}
當心,這可能被認爲是不好的做法,併爲更長遠的代碼我們建議你把一個非運行時異常,並在方法的簽名定義它。
刪除功能本身捕獲的Throwable已經是不好的做法(和許多代碼質量檢查工具標記爲此類)。將它包裝在RuntimeException中並重新拋出它?可怕!具有異常層次結構的整個觀點受到了破壞。
遠離檢查異常的'趨勢'實際上有點微妙。在架構層之間(或者例如在框架API邊界),定義一個或多個有意義的異常類型並在其中包含任何特定於實現的錯誤(例如查看Spring或Hibernate)是常見做法。
使例外檢查與否是風格問題。如果調用者很可能願意並且能夠處理錯誤情況,那麼我會檢查它(例如檢測到併發更新),否則不檢查(例如,數據庫連接錯誤)。未經檢查的異常應該通過應用程序代碼「冒泡」(即不被捕獲)並通過顯示某種錯誤頁面/屏幕在高層處理。
關於「不好的做法」,實際上,趨勢遠離檢查異常,以支持未檢查(「運行時」)異常,您仍然可以在方法簽名中定義運行時異常。 – SingleShot 2009-10-04 15:57:30
@SS這是一個非常糟糕的想法的一個原因是,包裝在RuntimeException中是更改傳播的異常。這使得堆棧中的東西很難處理異常。 – 2009-10-05 01:11:07