處理Java異常的10個最佳實踐

喝水會長肉發表於2021-12-16

線上程式碼不要使用printStackTrace()

寫完程式碼後請一定要檢查下,程式碼中千萬不要有printStackTrace()。因為printStackTrace()只會在控制檯上輸出錯誤的堆疊資訊,他只適合於用來程式碼除錯。

真正需要記錄異常,請使用日誌記錄。

永遠不要在catch塊中吞掉異常


catch 
(NoSuchMethodException e
) 
{

  return null ;
}

永遠不要不處理異常,而是返回null,這樣異常就會被吞掉,無法獲取到任何失敗資訊,會給日後的問題排查帶來巨大困難。

在需要的地方宣告特定的受檢異常


public 
void 
foo
(
) throws Exception 
{ 
//錯誤做法

}

一定要儘量避免上面的程式碼,因為他的呼叫者完全不知道錯誤的原因到底是什麼。

在方法宣告中,可以由方法丟擲一些特定受檢異常。如果有多個,那就分別丟擲多個,這樣這個方法的使用者才會分別針對每個異常做特定的處理,從而避免發生故障。


public 
void 
foo
(
) throws SpecificException1
, SpecificException2 
{ 

//正確做法
}
### 始終只捕獲那些可以處理的異常

catch (NoSuchMethodException e )
{
    throw e ; //這程式碼一點用都沒有
}

這是一個基本概念,當你能夠處理他時,你再捕獲這個異常,否則永遠都不要捕獲他。

如果你不能在catch塊中處理它,那麼就不要先捕獲再直接丟擲,這樣沒有任何意義。

儘量捕獲特定的子類,而不是直接捕獲Exception類


try 
{

    someMethod ( ) ;
}
catch (Exception e )
{
    LOGGER . error ( "method has failed" , e ) ;
}

以上程式碼,最大的問題就是,如果someMethod()的開發者在裡面新增了一個特定的異常,並且預期是呼叫方能夠特殊的對他進行處理。

但是呼叫者直接catch了Exception類,就會導致永遠無法知道someMethod的具體變化細節。這久可能導致在執行的過程中在某一個時間點程式崩潰。

永遠不要捕獲Throwable類

這是一個嚴重的問題,因為Java中的Error也可以是Throwable的子類。但是Error是Java虛擬機器本身無法控制的。Java虛擬機器甚至可能不會在出現任何錯誤時請求使用者的catch子句。

始終在自定義異常中覆蓋原有的異常,這樣堆疊跟蹤就不會丟失


catch 
(NoSuchMethodException e
) 
{

//vx耗:mbz_java_panlong 十年開發經驗程式設計師,免費解答,備註“MI”即可

throw new MyServiceException ( "Some information: " + e . getMessage ( ) ) ;   //錯誤做法
}

上面的命令可能會丟失掉主異常的堆疊跟蹤。正確的方法是:


catch 
(NoSuchMethodException e
) 
{

    throw new MyServiceException ( "Some information: " , e ) ;   //正確做法
}

可以記錄異常或丟擲異常,但不要同時做


catch 
(NoSuchMethodException e
) 
{

  LOGGER . error ( "Some information" , e ) ;
  throw e ;
}

如上面的程式碼所示,丟擲和日誌記錄可能會在日誌檔案中產生多個日誌訊息。

這就會導致同一個問題,卻在日誌中有很多不同的錯誤資訊,使得開發人員陷入混亂。

永遠不要在finally中丟擲異常


try 
{

someMethod ( ) ;   //丟擲 exceptionOne
}
finally {
  //java學習交流:737251827  進入可領取學習資源及對十年開發經驗大佬提問,免費解答!
cleanUp ( ) ;     //如果在這裡再丟擲一個異常,那麼try中的exceptionOne將會丟失forever
}

在上面的例子中,如果someMethod()丟擲一個異常,並且在finally塊中,cleanUp()也丟擲一個異常,那麼初始的exceptionOne(正確的錯誤異常)將永遠丟失。

如果您不打算處理異常,請使用finally塊而不是catch塊


try 
{

  someMethod ( ) ;
}
finally
{
  cleanUp ( ) ;    
}

這也是一個很好的實踐。如果在你的方法中訪問其他方法,而該方法丟擲了異常你不想處理,但是仍然需要做一些清理工作,那麼在finally塊中進行清理。不要使用catch塊。

(全文完)



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70010294/viewspace-2847915/,如需轉載,請註明出處,否則將追究法律責任。

相關文章