<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Java 處理 Exception 的 9 個(gè)最佳實(shí)踐!

          共 5467字,需瀏覽 11分鐘

           ·

          2020-07-27 18:33



          原文: https://dzone.com/articles/9-best-practices-to-handle-exceptions-in-java?

          譯者:颯然Hang

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



          在Java中處理異常并不是一個(gè)簡(jiǎn)單的事情。不僅僅初學(xué)者很難理解,即使一些有經(jīng)驗(yàn)的開(kāi)發(fā)者也需要花費(fèi)很多時(shí)間來(lái)思考如何處理異常,包括需要處理哪些異常,怎樣處理等等。這也是絕大多數(shù)開(kāi)發(fā)團(tuán)隊(duì)都會(huì)制定一些規(guī)則來(lái)規(guī)范對(duì)異常的處理的原因。而團(tuán)隊(duì)之間的這些規(guī)范往往是截然不同的。

          本文給出幾個(gè)被很多團(tuán)隊(duì)使用的異常處理最佳實(shí)踐。

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

          當(dāng)使用類似InputStream這種需要使用后關(guān)閉的資源時(shí),一個(gè)常見(jiàn)的錯(cuò)誤就是在try塊的最后關(guān)閉資源。

          public void doNotCloseResourceInTry() {
          FileInputStream inputStream = null;
          try {
          File file = new File("./tmp.txt");
          inputStream = new FileInputStream(file);
          // use the inputStream to read a file
          // do NOT do this
          inputStream.close();
          } catch (FileNotFoundException e) {
          log.error(e);
          } catch (IOException e) {
          log.error(e);
          }
          }

          上述代碼在沒(méi)有任何exception的時(shí)候運(yùn)行是沒(méi)有問(wèn)題的。但是當(dāng)try塊中的語(yǔ)句拋出異常或者自己實(shí)現(xiàn)的代碼拋出異常,那么就不會(huì)執(zhí)行最后的關(guān)閉語(yǔ)句,從而資源也無(wú)法釋放。

          合理的做法則是將所有清理的代碼都放到finally塊中或者使用try-with-resource語(yǔ)句。

          public void closeResourceInFinally() {
          FileInputStream inputStream = null;
          try {
          File file = new File("./tmp.txt");
          inputStream = new FileInputStream(file);
          // use the inputStream to read a file
          } catch (FileNotFoundException e) {
          log.error(e);
          } finally {
          if (inputStream != null) {
          try {
          inputStream.close();
          } catch (IOException e) {
          log.error(e);
          }
          }
          }
          }

          public void automaticallyCloseResource() {
          File file = new File("./tmp.txt");
          try (FileInputStream inputStream = new FileInputStream(file);) {
          // use the inputStream to read a file
          } catch (FileNotFoundException e) {
          log.error(e);
          } catch (IOException e) {
          log.error(e);
          }
          }

          2. 指定具體的異常

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

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

          如上,NumberFormatException字面上即可以看出是數(shù)字格式化錯(cuò)誤。

          3. 對(duì)異常進(jìn)行文檔說(shuō)明

          當(dāng)在方法上聲明拋出異常時(shí),也需要進(jìn)行文檔說(shuō)明。和前面的一點(diǎn)一樣,都是為了給調(diào)用者提供盡可能多的信息,從而可以更好地避免/處理異常。異常處理的 10 個(gè)最佳實(shí)踐,這篇也推薦看下。

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

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

          4. 拋出異常的時(shí)候包含描述信息

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

          但這里并不是說(shuō)要對(duì)錯(cuò)誤信息長(zhǎng)篇大論,因?yàn)楸緛?lái)Exception的類名就能夠反映錯(cuò)誤的原因,因此只需要用一到兩句話描述即可。

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

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

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

          現(xiàn)在很多IDE都能智能提示這個(gè)最佳實(shí)踐,當(dāng)你試圖首先捕獲最籠統(tǒng)的異常時(shí),會(huì)提示不能達(dá)到的代碼。當(dāng)有多個(gè)catch塊中,按照捕獲順序只有第一個(gè)匹配到的catch塊才能執(zhí)行。因此,如果先捕獲IllegalArgumentException,那么則無(wú)法運(yùn)行到對(duì)NumberFormatException的捕獲。

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

          6. 不要捕獲Throwable

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

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

          7. 不要忽略異常

          很多時(shí)候,開(kāi)發(fā)者很有自信不會(huì)拋出異常,因此寫(xiě)了一個(gè)catch塊,但是沒(méi)有做任何處理或者記錄日志。

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

          但現(xiàn)實(shí)是經(jīng)常會(huì)出現(xiàn)無(wú)法預(yù)料的異常或者無(wú)法確定這里的代碼未來(lái)是不是會(huì)改動(dòng)(刪除了阻止異常拋出的代碼),而此時(shí)由于異常被捕獲,使得無(wú)法拿到足夠的錯(cuò)誤信息來(lái)定位問(wèn)題。合理的做法是至少要記錄異常的信息。

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

          8. 不要記錄并拋出異常

          可以發(fā)現(xiàn)很多代碼甚至類庫(kù)中都會(huì)有捕獲異常、記錄日志并再次拋出的邏輯。如下:

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

          這個(gè)處理邏輯看著是合理的。但這經(jīng)常會(huì)給同一個(gè)異常輸出多條日志。如下:

          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)

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

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

          因此,僅僅當(dāng)想要處理異常時(shí)才去捕獲,否則只需要在方法簽名中聲明讓調(diào)用者去處理。

          9. 包裝異常時(shí)不要拋棄原始的異常

          捕獲標(biāo)準(zhǔn)異常并包裝為自定義異常是一個(gè)很常見(jiàn)的做法。這樣可以添加更為具體的異常信息并能夠做針對(duì)的異常處理。

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

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

          總結(jié)

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

          最后免費(fèi)給大家分享50個(gè)Java項(xiàng)目實(shí)戰(zhàn)資料,涵蓋入門、進(jìn)階各個(gè)階段學(xué)習(xí)內(nèi)容,可以說(shuō)非常全面了。大部分視頻還附帶源碼,學(xué)起來(lái)還不費(fèi)勁!


          附上截圖。(下面有下載方式)。


          項(xiàng)目領(lǐng)取方式:

          掃描下方公眾號(hào)回復(fù):50

          可獲取下載鏈接

          ???

          ?長(zhǎng)按上方二維碼?2 秒
          回復(fù)「50」即可獲取資料


          點(diǎn)贊是最大的支持?

          瀏覽 30
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人视频在线观看18 | 18AV在线观看 | 婷婷av在线 | 久就热精品视频在线 | 91性爱视频在线观看 |