<del id="nnjnj"></del><track id="nnjnj"></track>

<p id="nnjnj"></p>

<address id="nnjnj"></address>

    <pre id="nnjnj"><pre id="nnjnj"></pre></pre>

      <noframes id="nnjnj"><ruby id="nnjnj"><ruby id="nnjnj"></ruby></ruby>

      • 自動秒收錄
      • 軟件:1973
      • 資訊:57811|
      • 收錄網站:279872|

      IT精英團

      Java處理異常的9個最佳實踐 你做得對嗎?

      Java處理異常的9個最佳實踐 你做得對嗎?

      瀏覽次數:
      評論次數:
      編輯: 景同
      信息來源: ITPUB
      更新日期: 2022-05-18 20:57:03
      摘要

      原文:https://dzone.com/articles/9-best-practices-to-handle-exceptions-in-java譯者:颯然Hang譯文:http://www.r

      • 正文開始
      • 相關閱讀
      • 推薦作品

      original : https://dzone.com/articles/9-處理java異常的最佳實踐

      譯者:薩然杭

      翻譯:http://www.rowkey.me/blog/2017/09/17/java-exception/

      在Java中處理異常不是一件簡單的事情。不僅初學者難以理解,就連一些有經驗的開發人員也需要花大量的時間去思考如何處理異常,包括哪些異常需要處理,如何處理等等。這也是為什么大多數開發團隊會制定一些規則來規范異常的處理。而團隊之間的這些規范往往是完全不同的。

      本文給出了許多團隊使用的異常處理的幾個最佳實踐。

      1. 在Finally塊中清理資源或者使用try-with-resource語句

      當使用像InputStream這樣需要在使用后關閉的資源時,一個常見的錯誤是在try塊的末尾關閉資源。

      public void doNotCloseResourceInTry(){

      FileInputStream輸入流=null

      嘗試{

      File file=新文件('。/tmp . txt ');

      inputStream=新文件inputStream(文件);

      //使用inputStream讀取文件

      //不要這樣做

      inputstream . close();

      } catch(file not found exception e){

      日志錯誤(e);

      } catch (IOException e) {

      日志錯誤(e);

      }

      }

      上面的代碼運行沒有任何異常就沒有問題。但是,當try塊中的語句拋出異?;蛘咦陨韺崿F的代碼拋出異常時,最后一條關閉語句將不會執行,資源無法釋放。

      合理的方法是將所有清理過的代碼放在finally塊中,或者使用try-with-resource語句。

      public void closeResourceInFinally(){

      FileInputStream輸入流=null

      嘗試{

      File file=新文件('。/tmp . txt ');

      inputStream=新文件inputStream(文件);

      //使用inputStream讀取文件

      } catch(file not found exception e){

      日志錯誤(e);

      }最后{

      if (inputStream!=null) {

      嘗試{

      inputstream . close();

      } catch (IOException e) {

      日志錯誤(e);

      }

      }

      }

      }

      public void automaticallyCloseResource(){

      File file=新文件('。/tmp . txt ');

      try(file inputStream inputStream=new file inputStream(file);) {

      //使用inputStream讀取文件

      } catch(file not found exception e){

      日志錯誤(e);

      } catch (IOException e) {

      log.erro

      r(e);
      }
      }

      2. 指定具體的異常

      盡可能的使用最具體的異常來聲明方法,這樣才能使得代碼更容易理解。

      public void doNotDoThis() throws Exception {
      ...
      }
      public void doThis() throws NumberFormatException {
      ...
      }

      如上,NumberFormatException字面上即可以看出是數字格式化錯誤。

      3. 對異常進行文檔說明

      當在方法上聲明拋出異常時,也需要進行文檔說明。和前面的一點一樣,都是為了給調用者提供盡可能多的信息,從而可以更好地避免/處理異常。

      在Javadoc中加入throws聲明,并且描述拋出異常的場景。

      /**
      * This method does something extremely useful ...
      *
      * @param input
      * @throws MyBusinessException if ... happens
      */
      public void doSomething(String input) throws MyBusinessException {
      ...
      }

      4. 拋出異常的時候包含描述信息

      在拋出異常時,需要盡可能精確地描述問題和相關信息,這樣無論是打印到日志中還是監控工具中,都能夠更容易被人閱讀,從而可以更好地定位具體錯誤信息、錯誤的嚴重程度等。

      但這里并不是說要對錯誤信息長篇大論,因為本來Exception的類名就能夠反映錯誤的原因,因此只需要用一到兩句話描述即可。

      try {
      new Long("xyz");
      } catch (NumberFormatException e) {
      log.error(e);
      }

      NumberFormatException即告訴了這個異常是格式化錯誤,異常的額外信息只需要提供這個錯誤字符串即可。當異常的名稱不夠明顯的時候,則需要提供盡可能具體的錯誤信息。

      5. 首先捕獲最具體的異常

      現在很多IDE都能智能提示這個最佳實踐,當你試圖首先捕獲最籠統的異常時,會提示不能達到的代碼。當有多個catch塊中,按照捕獲順序只有第一個匹配到的catch塊才能執行。因此,如果先捕獲IllegalArgumentException,那么則無法運行到對NumberFormatException的捕獲。

      public void catchMostSpecificExceptionFirst() {
      try {
      doSomething("A message");
      } catch (NumberFormatException e) {
      log.error(e);
      } catch (IllegalArgumentException e) {
      log.error(e)
      }
      }

      6. 不要捕獲Throwable

      Throwable是所有異常和錯誤的父類。你可以在catch語句中捕獲,但是永遠不要這么做。如果catch了throwable,那么不僅僅會捕獲所有exception,還會捕獲error。而error是表明無法恢復的jvm錯誤。因此除非絕對肯定能夠處理或者被要求處理error,不要捕獲throwable。

      public void doNotCatchThrowable() {
      try {
      // do something
      } catch (Throwable t) {
      // don't do this!
      }
      }

      7. 不要忽略異常

      很多時候,開發者很有自信不會拋出異常,因此寫了一個catch塊,但是沒有做任何處理或者記錄日志。

      public void doNotIgnoreExceptions() {
      try {
      // do something
      } catch (NumberFormatException e) {
      // this will never happen
      }
      }

      但現實是經常會出現無法預料的異?;蛘邿o法確定這里的代碼未來是不是會改動(刪除了阻止異常拋出的代碼),而此時由于異常被捕獲,使得無法拿到足夠的錯誤信息來定位問題。合理的做法是至少要記錄異常的信息。

      public void logAnException() {
      try {
      // do something
      } catch (NumberFormatException e) {
      log.error("This should never happen: " + e);
      }
      }

      8. 不要記錄并拋出異常

      可以發現很多代碼甚至類庫中都會有捕獲異常、記錄日志并再次拋出的邏輯。如下:

      try {
      new Long("xyz");
      } catch (NumberFormatException e) {
      log.error(e);
      throw e;
      }

      這個處理邏輯看著是合理的。但這經常會給同一個異常輸出多條日志。如下:

      17:44:28,945 ERROR TestExceptionHandling:65 - java.lang.NumberFormatException: For input string: "xyz"
      Exception in thread "main" java.lang.NumberFormatException: For input string: "xyz"
      at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
      at java.lang.Long.parseLong(Long.java:589)
      at java.lang.Long.(Long.java:965)
      at com.stackify.example.TestExceptionHandling.logAndThrowException(TestExceptionHandling.java:63)
      at com.stackify.example.TestExceptionHandling.main(TestExceptionHandling.java:58)

      如上所示,后面的日志也沒有附加更有用的信息。如果想要提供更加有用的信息,那么可以將異常包裝為自定義異常。

      public void wrapException(String input) throws MyBusinessException {
      try {
      // do something
      } catch (NumberFormatException e) {
      throw new MyBusinessException("A message that describes the error.", e);
      }
      }

      因此,僅僅當想要處理異常時才去捕獲,否則只需要在方法簽名中聲明讓調用者去處理。

      9. 包裝異常時不要拋棄原始的異常

      捕獲標準異常并包裝為自定義異常是一個很常見的做法。這樣可以添加更為具體的異常信息并能夠做針對的異常處理。

      需要注意的是,包裝異常時,一定要把原始的異常設置為cause(Exception有構造方法可以傳入cause)。否則,丟失了原始的異常信息會讓錯誤的分析變得困難。

      public void wrapException(String input) throws MyBusinessException {
      try {
      // do something
      } catch (NumberFormatException e) {
      throw new MyBusinessException("A message that describes the error.", e);
      }
      }

      總結

      綜上可知,當拋出或者捕獲異常時,有很多不一樣的東西需要考慮。其中的許多點都是為了提升代碼的可閱讀性或者api的可用性。異常不僅僅是一個錯誤控制機制,也是一個溝通媒介,因此與你的協作者討論這些最佳實踐并制定一些規范能夠讓每個人都理解相關的通用概念并且能夠按照同樣的方式使用它們。

      標簽:異常 拋出 錯誤
      提高Java字符串編碼和解碼性能的技巧
      ? 上一篇 2022-05-18
      高并發服務的幾點優化經驗
      下一篇 ? 2022-05-18
      • 如何在Ubuntu中保留文件系統并備份當前開發板鏡像
        0閱讀 0條評論 個贊
        在Ubuntu保留文件系統或者說備份當前開發板鏡像的需求在不斷增加。比如Ubuntu文件系統需要安裝庫文件的話直接使用apt-get工具就可以下載,但由于需要下載的核心板較多,比較費時間,這時需要將安……
      • 國產核心板全志T507助力消防系統升級
        0閱讀 0條評論 個贊
        9月16日下午,位于湖南長沙市區內的中國電信大樓發生火災,建筑高度218米,現場濃煙滾滾,數十層樓體燃燒劇烈。消防救援人員趕到現場后很快將火勢控制住,目前大樓火勢已被撲滅,所幸未發現人員傷亡。湖南電信……
      • 教大家如何處理Spring Boot易流中的用戶和群體!
        0閱讀 0條評論 個贊
        1.準備工作2.用戶操作2.1添加用戶2.2修改用戶2.3刪除用戶2.4查詢用戶3.組操作3.1添加組3.2修改組3.3刪除組3.4查詢組4.查看表詳情雖然說我們在實際開發中,……
      • 從PG15開始WAL壓縮優化
        0閱讀 0條評論 個贊
        PG15傳聞中的超級令人激動的功能大多數跳票了,年初我也寫過一個關于PG15新功能跳票的文章。PG15BETA已經發出幾個月了,似乎PG15里令人激動人心的功能不多,不過從長長的新功能列表里,……
      • 深入了解美團葉子發射器開源方案
        0閱讀 0條評論 個贊
        大家好,我是樹哥。之前我們有聊過「如何設計一個分布式ID發號器」,其中有講過4種解決方案,分別是:UUID類雪花算法數據庫自增主鍵Redis原子自增美團以第2、3種解決方案為基礎,開發出……
      發表評論 共有條評論
      用戶名: 密碼:
      驗證碼: 匿名發表
      • SQL Server 2005分區模板和實例
        0閱讀 0條評論 個贊
        一、場景這一段時間使用SQLServer2005對幾個系統進行表分區,這幾個系統都有一些特點,比如數據庫某張表持續增長,給數據庫帶來了很大的壓力?,F在假如提供一臺新的服務器,那么我們應該如何規劃……
      • 談談動態線程池的9個場景(改進版)
        0閱讀 0條評論 個贊
        大家好,我是小馬哥。線程池是一種基于池化思想管理線程的工具,使用線程池可以減少創建銷毀線程的開銷,避免線程過多導致系統資源耗盡。在高并發以及大批量的任務處理場景,線程池的使用是必不可少的?!?/div>
      • 深入了解美團葉子發射器開源方案
        0閱讀 0條評論 個贊
        大家好,我是樹哥。之前我們有聊過「如何設計一個分布式ID發號器」,其中有講過4種解決方案,分別是:UUID類雪花算法數據庫自增主鍵Redis原子自增美團以第2、3種解決方案為基礎,開發出……
      • SQL Server批量完整備份
        0閱讀 0條評論 個贊
        一.本文所涉及的內容(Contents)本文所涉及的內容(Contents)背景(Contexts)實現代碼(SQLCodes)實現方式一(One)實現方式二(Two)實現方式三(Three)參考文……
      • [設計模式] Java設計模式-橋模式
        0閱讀 0條評論 個贊
        目錄【設計模式】Java設計模式-橋接模式簡介橋接模式實例代碼示例①、品牌接口②、汽車品牌③、抽象汽車類④、汽車類型子類⑤、橋接模式測試1|1簡介橋接(Bridge)是用于把抽象化與實現化解耦,使……
      • Hadoop JMX監控和預警
        0閱讀 0條評論 個贊
        .css-1yuhvjn{margin-top:16px;}.css-3jt6os.FileLinkCard{-webkit-align-items:center;-webkit-box-align……
      • SQL Server備份和還原攻略
        0閱讀 0條評論 個贊
        一、知識點完全備份:備份全部選中的文件夾,并不依賴文件的存檔屬性來確定備份那些文件。(在備份過程中,任何現有的標記都被清除,每個文件都被標記為已備份,換言之,清除存檔屬性)。完全備份也叫完整備份。差異……
      • 基于位置變化的市縣彈出引導切換
        31閱讀 0條評論 個贊
        目錄1.背景2.模型方案產出3.總結01背景58App業務中有城市和縣域兩個首頁,兩者中間有一個過渡選擇頁,用戶通過點擊該頁面下的條目內容可以切換到對應條目的首頁;比如:點擊“北京”會跳轉到北京(市)……
      • 數據庫發展史1-傳統數據庫
        0閱讀 0條評論 個贊
        1946年,美國賓夕法尼亞大學誕生了人類第一臺電子計算機--ENIAC(ElectronicNumericalIntegratorAndComputer,即電子數字積分計算機),這個占地170……
      • Sql Server系列:分區表操作
        0閱讀 0條評論 個贊
        1.分區表簡介分區表在邏輯上是一個表,而物理上是多個表。從用戶角度來看,分區表和普通表是一樣的。使用分區表的主要目的是為改善大型表以及具有多個訪問模式的表的可伸縮性和可管理性。分區表是把數據……
      • 國產核心板全志T507助力消防系統升級
        0閱讀 0條評論 個贊
        9月16日下午,位于湖南長沙市區內的中國電信大樓發生火災,建筑高度218米,現場濃煙滾滾,數十層樓體燃燒劇烈。消防救援人員趕到現場后很快將火勢控制住,目前大樓火勢已被撲滅,所幸未發現人員傷亡。湖南電信……
      • 人工智能OPS的莫拉維克悖論
        3閱讀 0條評論 個贊
        莫拉維克的悖論是人工智能和機器人研究人員觀察到,與傳統假設相反,推理需要很少的計算,但感覺運動和感知技能需要大量的計算資源。該原則由HansMoravec、RodneyBrooks、Marvin……
      • SQL Server聯接方式
        0閱讀 0條評論 個贊
        0.參考文獻MicrosoftSQLServer企業級平臺管理實踐看懂SqlServer查詢計劃1.測試數據準備參考:SqlServer中的表訪問方式TableScan,IndexScan……
      • 簡單分析下的GOLDENDB
        0閱讀 0條評論 個贊
        GOLDENDB是金融行業使用的比較廣泛的一個數據庫產品,以前也經常有朋友希望我寫幾篇分析GoldenDB數據庫的文章。說實在的這類文章不好寫,必須對某個產品有一定程度的了解,特別是真正上手用過之后,……
      • SpringMVC 01: SpringMVC第一個SpringMVC項目
        0閱讀 0條評論 個贊
        SpringMVCSpringMVC概述:是基于MVC開發模式的框架,用來優化控制器是Spring家族的一員,也具備IOC和AOP什么是MVC:它是一種開發模式,是模型視圖控制器的簡稱,所有的web應……
      • Java可以重新鎖定的那些東西(1)
        0閱讀 0條評論 個贊
        本文主要包含的內容:可重入鎖(ReedtrantLock)、公平鎖、非公平鎖、可重入性、同步隊列、CAS等概念的理解顯式鎖……
      • 開發者如何在應用后臺直接控制用戶的運動狀態?
        18閱讀 0條評論 個贊
        酷暑終于過去,很多人伴著涼爽的秋風開啟了新一輪的健身計劃。當用戶進行戶外運動或使用跑步機、橢圓機等器械時,他們會希望在運動健康類App里點擊即可開啟運動并記錄運動數據。而對于開發者自己開發的應用來說,……
      • :自古以來 特工程序就是兵家必敗之地
        0閱讀 0條評論 個贊
        正向代理的血案前幾天打算使用golang做一個代理程序,golang標準庫net/http/httputil已經提供了這樣的能力。一把梭之后發現必然返回403Forbidden,我直接在targe……
      • 面試官:談談你對mysql事務的認識?
        0閱讀 0條評論 個贊
        引言今天回頭繼續講講數據庫系列的文章。這篇文章屬于mysql數據庫系列,我們來談談事務方面的常見面試題。那么,具體題目有下面這些:1、講講為什么用事務?事務的四大特性?事務的隔離級別知道吧,你們生產……
      • 如何保持Mysql和Redis數據一致
        0閱讀 0條評論 個贊
        先闡明一下Mysql和Redis的關系:Mysql是數據庫,用來持久化數據,一定程度上保證數據的可靠性;Redis是用來當緩存,用來提升數據訪問的性能。關于如何保證Mysql和Redis中的數據一致(……
      最近發布資訊
      更多
      警花高潮嗷嗷叫
      <del id="nnjnj"></del><track id="nnjnj"></track>

      <p id="nnjnj"></p>

      <address id="nnjnj"></address>

        <pre id="nnjnj"><pre id="nnjnj"></pre></pre>

          <noframes id="nnjnj"><ruby id="nnjnj"><ruby id="nnjnj"></ruby></ruby>