<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      轉-Java 異常處理的 20 個最佳實踐,你知道幾個?

      ?

      作  者武培軒
      出  處http://www.rzrgm.cn/wupeixuan
      原文鏈接http://www.rzrgm.cn/wupeixuan/p/11746117.html

      異常處理是 Java 開發中的一個重要部分,是為了處理任何錯誤狀況,比如資源不可訪問,非法輸入,空輸入等等。Java 提供了幾個異常處理特性,以try,catch 和 finally 關鍵字的形式內建于語言自身之中。Java 編程語言也允許創建新的自定義異常,并通過使用 throw 和 throws關鍵字拋出它們。在Java編程中,Java 的異常處理不單單是知道語法這么簡單,它必須遵循標準的 JDK 庫,和處理錯誤和異常的開源代碼。

      這里我們將討論一些關于異常處理的 Java 最佳實踐。在我們討論異常處理的最佳實踐之前,先讓我們了解下幾個重要的概念,那就是什么是異常以及異常的分類。

      1 什么是異常?

      異常的英文單詞是 exception,異常本質上是程序上的錯誤,包括程序邏輯錯誤和系統錯誤。比如使用空的引用、數組下標越界、內存溢出錯誤等,這些都是意外的情況,背離我們程序本身的意圖。錯誤在我們編寫程序的過程中會經常發生,包括編譯期間和運行期間的錯誤,在編譯期間出現的錯誤有編譯器幫助我們一起修正,然而運行期間的錯誤便不是編譯器力所能及了,并且運行期間的錯誤往往是難以預料的。假若程序在運行期間出現了錯誤,如果置之不理,程序便會終止或直接導致系統崩潰,顯然這不是我們希望看到的結果。

      如何對運行期間出現的錯誤進行處理和補救呢?Java 提供了異常機制來進行處理,通過異常機制來處理程序運行期間出現的錯誤。通過異常機制,我們可以更好地提升程序的健壯性。

      2 異常分類

      Java 把異常當作對象來處理,并定義一個基類 java.lang.Throwable 作為所有異常的超類。

      Java 包括三種類型的異常: 檢查性異常(checked exceptions)、非檢查性異常(unchecked Exceptions) 和錯誤(errors)。

      • 檢查性異常(checked exceptions) 是必須在在方法的 throws 子句中聲明的異常。它們擴展了異常,旨在成為一種“在你面前”的異常類型。JAVA希望你能夠處理它們,因為它們以某種方式依賴于程序之外的外部因素。檢查的異常表示在正常系統操作期間可能發生的預期問題。 當你嘗試通過網絡或文件系統使用外部系統時,通常會發生這些異常。 大多數情況下,對檢查性異常的正確響應應該是稍后重試,或者提示用戶修改其輸入。
      • 非檢查性異常(unchecked Exceptions) 是不需要在throws子句中聲明的異常。 由于程序錯誤,JVM并不會強制你處理它們,因為它們大多數是在運行時生成的。 它們擴展了 RuntimeException。 最常見的例子是 NullPointerException, 未經檢查的異常可能不應該重試,正確的操作通常應該是什么都不做,并讓它從你的方法和執行堆棧中出來。
      • 錯誤(errors) 是嚴重的運行時環境問題,肯定無法恢復。 例如 OutOfMemoryError,LinkageError 和 StackOverflowError,通常會讓程序崩潰。

      所有不是 Runtime Exception 的異常,統稱為 Checked Exception,又被稱為檢查性異常。這類異常的產生不是程序本身的問題,通常由外界因素造成的。為了預防這些異常產生時,造成程序的中斷或得到不正確的結果,Java 要求編寫可能產生這類異常的程序代碼時,一定要去做異常的處理。

      Java 語言將派生于 RuntimeException 類或 Error 類的所有異常稱為非檢查性異常。

      Java 異常層次結構圖如下圖所示:

      Java中的異常層次結構

      在了解了異常的基本概念以及分類后,現在讓我們開始探索異常處理的最佳實踐吧。

      3 異常處理最佳實踐

      3.1 不要忽略捕捉的異常

      catch (NoSuchMethodException e) {
         return null;
      }
      

      雖然捕捉了異常但是卻沒有做任何處理,除非你確信這個異常可以忽略,不然不應該這樣做。這樣會導致外面無法知曉該方法發生了錯誤,無法確定定位錯誤原因。

      3.2 在你的方法里拋出定義具體的檢查性異常

      public void foo() throws Exception { //錯誤方式
      }
      

      一定要避免出現上面的代碼示例,它破壞了檢查性異常的目的。 聲明你的方法可能拋出的具體檢查性異常,如果只有太多這樣的檢查性異常,你應該把它們包裝在你自己的異常中,并在異常消息中添加信息。 如果可能的話,你也可以考慮代碼重構。

      public void foo() throws SpecificException1, SpecificException2 { //正確方式
      }
      

      3.3 捕獲具體的子類而不是捕獲 Exception 類

      try {
         someMethod();
      } catch (Exception e) { //錯誤方式
         LOGGER.error("method has failed", e);
      }
      

      捕獲異常的問題是,如果稍后調用的方法為其方法聲明添加了新的檢查性異常,則開發人員的意圖是應該處理具體的新異常。如果你的代碼只是捕獲異常(或 Throwable),永遠不會知道這個變化,以及你的代碼現在是錯誤的,并且可能會在運行時的任何時候中斷。

      3.4 永遠不要捕獲 Throwable 類

      這是一個更嚴重的麻煩,因為 Java Error 也是 Throwable 的子類,Error 是 JVM 本身無法處理的不可逆轉的條件,對于某些 JVM 的實現,JVM 可能實際上甚至不會在 Error 上調用 catch 子句。

      3.5 始終正確包裝自定義異常中的異常,以便堆棧跟蹤不會丟失

      catch (NoSuchMethodException e) {
         throw new MyServiceException("Some information: " + e.getMessage());  //錯誤方式
      }
      

      這破壞了原始異常的堆棧跟蹤,并且始終是錯誤的,正確的做法是:

      catch (NoSuchMethodException e) {
         throw new MyServiceException("Some information: " , e);  //正確方式
      }
      

      3.6 要么記錄異常要么拋出異常,但不要一起執行

      catch (NoSuchMethodException e) {  
      //錯誤方式 
         LOGGER.error("Some information", e);
         throw e;
      }
      

      正如上面的代碼中,記錄和拋出異常會在日志文件中產生多條日志消息,代碼中存在單個問題,并且對嘗試分析日志的同事很不友好。

      3.7 finally 塊中永遠不要拋出任何異常

      try {
        someMethod();  //Throws exceptionOne
      } finally {
        cleanUp();    //如果finally還拋出異常,那么exceptionOne將永遠丟失
      }
      

      只要 cleanUp() 永遠不會拋出任何異常,上面的代碼沒有問題,但是如果 someMethod() 拋出一個異常,并且在 finally 塊中,cleanUp() 也拋出另一個異常,那么程序只會把第二個異常拋出來,原來的第一個異常(正確的原因)將永遠丟失。如果在 finally 塊中調用的代碼可能會引發異常,請確保要么處理它,要么將其記錄下來。永遠不要讓它從 finally 塊中拋出來。

      3.8 始終只捕獲實際可處理的異常

      catch (NoSuchMethodException e) {
         throw e; //避免這種情況,因為它沒有任何幫助
      }
      

      這是最重要的概念,不要為了捕捉異常而捕捉,只有在想要處理異常時才捕捉異常,或者希望在該異常中提供其他上下文信息。如果你不能在 catch 塊中處理它,那么最好的建議就是不要只為了重新拋出它而捕獲它。

      3.9 不要使用 printStackTrace() 語句或類似的方法

      完成代碼后,切勿忽略 printStackTrace(),最終別人可能會得到這些堆棧,并且對于如何處理它完全沒有任何方法,因為它不會附加任何上下文信息。

      3.10 對于不打算處理的異常,直接使用 finally

      try {
        someMethod();  //Method 2
      } finally {
        cleanUp();    //do cleanup here
      }
      

      這是一個很好的做法,如果在你的方法中你正在訪問 Method 2,而 Method 2 拋出一些你不想在 Method 1 中處理的異常,但是仍然希望在發生異常時進行一些清理,然后在 finally 塊中進行清理,不要使用 catch 塊。

      3.11 記住早 throw 晚 catch 原則

      這可能是關于異常處理最著名的原則,簡單說,應該盡快拋出(throw)異常,并盡可能晚地捕獲(catch)它。應該等到有足夠的信息來妥善處理它。

      這個原則隱含地說,你將更有可能把它放在低級方法中,在那里你將檢查單個值是否為空或不適合。而且你會讓異常堆棧跟蹤上升好幾個級別,直到達到足夠的抽象級別才能處理問題。

      3.12 在異常處理后清理資源

      如果你正在使用數據庫連接或網絡連接等資源,請確保清除它們。如果你正在調用的 API 僅使用非檢查性異常,則仍應使用 try-finally 塊來清理資源。 在 try 模塊里面訪問資源,在 finally 里面最后關閉資源。即使在訪問資源時發生任何異常,資源也會優雅地關閉。

      3.13 只拋出和方法相關的異常

      相關性對于保持應用程序清潔非常重要。一種嘗試讀取文件的方法,如果拋出 NullPointerException,那么它不會給用戶任何相關的信息。相反,如果這種異常被包裹在自定義異常中,則會更好。NoSuchFileFoundException 則對該方法的用戶更有用。

      3.14 切勿在程序中使用異常來進行流程控制

      不要在項目中出現使用異常來處理應用程序邏輯。永遠不要這樣做,它會使代碼很難閱讀和理解。

      3.15 盡早驗證用戶輸入以在請求處理的早期捕獲異常

      始終要在非常早的階段驗證用戶輸入,甚至在達到 controller 之前,它將幫助你把核心應用程序邏輯中的異常處理代碼量降到最低。如果用戶輸入出現錯誤,還可以保證與應用程序一致。

      例如:如果在用戶注冊應用程序中,遵循以下邏輯:

      1. 驗證用戶
      2. 插入用戶
      3. 驗證地址
      4. 插入地址
      5. 如果出問題回滾一切

      這是不正確的做法,它會使數據庫在各種情況下處于不一致的狀態,應該首先驗證所有內容,然后將用戶數據置于 dao 層并進行數據庫更新。正確的做法是:

      1. 驗證用戶
      2. 驗證地址
      3. 插入用戶
      4. 插入地址
      5. 如果問題回滾一切

      3.16 一個異常只能包含在一個日志中

      LOGGER.debug("Using cache sector A");
      LOGGER.debug("Using retry sector B");
      

      不要像上面這樣做,對多個 LOGGER.debug() 調用使用多行日志消息可能在你的測試用例中看起來不錯,但是當它在具有 100 個并行運行的線程的應用程序服務器的日志文件中顯示時,所有信息都輸出到相同的日志文件,即使它們在實際代碼中為前后行,但是在日志文件中這兩個日志消息可能會間隔 100 多行。應該這樣做:

      LOGGER.debug("Using cache sector A, using retry sector B");
      

      3.17 將所有相關信息盡可能地傳遞給異常

      有用的異常消息和堆棧跟蹤非常重要,如果你的日志不能定位異常位置,那要日志有什么用呢?

      3.18 終止掉被中斷線程

      while (true) {
        try {
          Thread.sleep(100000);
        } catch (InterruptedException e) {} //別這樣做
        doSomethingCool();
      }
      

      InterruptedException 異常提示應該停止程序正在做的事情,比如事務超時或線程池被關閉等。

      應該盡最大努力完成正在做的事情,并完成當前執行的線程,而不是忽略 InterruptedException。修改后的程序如下:

      while (true) {
        try {
          Thread.sleep(100000);
        } catch (InterruptedException e) {
          break;
        }
      }
      doSomethingCool();
      

      3.19 對于重復的 try-catch,使用模板方法

      在代碼中有許多類似的 catch 塊是無用的,只會增加代碼的重復性,針對這樣的問題可以使用模板方法。

      例如,在嘗試關閉數據庫連接時的異常處理。

      class DBUtil{
          public static void closeConnection(Connection conn){
              try{
                  conn.close();
              } catch(Exception ex){
                  //Log Exception - Cannot close connection
              }
          }
      }
      

      這類的方法將在應用程序很多地方使用。不要把這塊代碼放的到處都是,而是定義上面的方法,然后像下面這樣使用它:

      public void dataAccessCode() {
          Connection conn = null;
          try{
              conn = getConnection();
              ....
          } finally{
              DBUtil.closeConnection(conn);
          }
      }
      

      3.20 使用 JavaDoc 中記錄應用程序中的所有異常

      把用 JavaDoc 記錄運行時可能拋出的所有異常作為一種習慣,其中也盡量包括用戶應該遵循的操作,以防這些異常發生。

      4 總結

      這篇文章首先介紹了什么是異常,以及異常的三種分類,然后通過 20 個最佳實踐來討論如何處理異常,希望能在以后異常處理的時候有所改進及感悟。

      posted @ 2024-07-12 10:17  booleandev  閱讀(52)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 漂亮的保姆hd完整版免费韩国| 久久大香萑太香蕉av黄软件| 欧美丰满熟妇bbbbbb| 亚洲成熟女人毛毛耸耸多| 久久久久无码中| 激情综合色综合啪啪开心| 亚洲国产成人午夜在线一区| 国产在线98福利播放视频| 中文字幕日韩有码第一页| 又爽又黄又无遮掩的免费视频| 久久久久久久一线毛片| 免费国产又色又爽又黄的网站| 女同另类激情在线三区| 亚洲免费观看一区二区三区| 国产中文三级全黄| 亚洲av无码专区在线亚| 日韩av综合中文字幕| 韩国三级网一区二区三区| 亚洲国产成人无码电影| 噜噜噜亚洲色成人网站∨| 乱女伦露脸对白在线播放| 亚洲成人av在线资源| 精品一区二区久久久久久久网站| 亚洲成人av综合一区| 精品 日韩 国产 欧美 视频| 亚洲精品亚洲人成人网| 国产精品综合在线免费看| 成人午夜视频一区二区无码| 亚洲午夜福利网在线观看| 精品人妻伦一二三区久久| 国产在线视频精品视频| 国产色无码专区在线观看| 日本在线 | 中文| 亚洲国产精品一区第二页| 欧美一区二区三区欧美日韩亚洲| 精品久久久久久久久午夜福利| 日韩视频中文字幕精品偷拍| 午夜福利一区二区在线看| 狠狠v日韩v欧美v| 亚洲中文字幕国产精品| 中文字幕日韩精品东京热|