欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java編程異常處理最佳實踐【推薦】

 更新時間:2017年10月27日 14:47:18   作者:一杯甜酒  
這篇文章主要介紹了Java編程異常處理最佳實踐【推薦】,具有一定參考價值,需要的朋友可以了解下。

Java中的異常處理不是一個簡單的話題。初學(xué)者很難理解,甚至有經(jīng)驗的開發(fā)人員也會花幾個小時來討論應(yīng)該如何拋出或處理這些異常。這就是為什么大多數(shù)開發(fā)團(tuán)隊都有自己的異常處理的規(guī)則和方法。如果你是一個團(tuán)隊的新手,你可能會驚訝于這些方法與你之前使用過的那些方法有多么不同。常見的異常類型:

NullPointerException -空指針引用異常
ClassCastException-類型強(qiáng)制轉(zhuǎn)換異常
lllegalArgumentException-傳遞非法參數(shù)異常
ArithmeticException-算術(shù)運(yùn)算異常
ArrayStoreException-向數(shù)組中存放與聲明類型不兼容對象異常
IndexOutOfBoundsException-下標(biāo)越界異常
NegativeArraySizeException-創(chuàng)建一個大小為負(fù)數(shù)的數(shù)組錯誤異常
NumberFormatException-數(shù)字格式異常
SecurityException-安全異常
UnsupportedOperationException-不支持的操作異常
EOFException:文件已結(jié)束異常
FileNotFoundException:文件未找到異常
SQLException:操作數(shù)據(jù)庫異常
IOException:輸入輸出異常
NoSuchMethodException:方法未找到異常

然而,有幾種異常處理的最佳方法被大多數(shù)開發(fā)團(tuán)隊所使用。下面為常見的幾種實用的異常處理方法!

1. 在Finally中清理資源或者使用Try-With-Resource語句

通常情況下,你在try中使用了一個資源,比如 InputStream ,之后需要關(guān)閉它。在這種情況下,一個常見的錯誤是在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);
  }
}

問題是,只要不拋出異常,這種方法就可以很好地運(yùn)行。try內(nèi)的所有語句都將被執(zhí)行,資源也會被關(guān)閉。

但是你在try里調(diào)用了一個或多個可能拋出異常的方法,或者自己拋出異常。這意味著可能無法到達(dá)try的末尾。因此,將不會關(guān)閉這些資源。

所以應(yīng)該將清理資源的代碼放入Finally中,或者使用Try-With-Resource語句。

使用Finally

相比于try,無論是在成功執(zhí)行try里的代碼后,或是在catch中處理了一個異常后,F(xiàn)inally里的內(nèi)容是一定會被執(zhí)行的。因此,可以確保清理所有已打開的資源。

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);
      }
    }
  }
}

Java 7的Try-With-Resource語句

另一個選擇是Try-With-Resource語句,在 introduction to Java exception handling 中更詳細(xì)地說明了這一點。
如果你的資源實現(xiàn)了 AutoCloseable 接口,就可以使用它,這正是大多數(shù)Java標(biāo)準(zhǔn)資源所做的。當(dāng)你在try子句中打開資源時,它將在try被執(zhí)行后自動關(guān)閉,或者處理一個異常。

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. 給出準(zhǔn)確的異常處理信息

你拋出的異常越具體越好。一定要記住,一個不太了解你代碼的同事,也許幾個月后,需要調(diào)用你的方法,并且處理這個異常。

因此,請確保提供盡可能多的信息,這會使你的API更容易理解。因此,你方法的調(diào)用者將能夠更好地處理異常,或者通過額外的檢查來避免它。

所以,要盡量能更好地描述你的異常處理信息,比如用 NumberFormatException 代替 IllegalArgumentException ,避免拋出一個不具體的異常。

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

3. 記錄你所指定的異常

當(dāng)你在方法中指定一個異常時,你應(yīng)該在Javadoc中記錄下它。這與前面提到的方法有著相同的目標(biāo):為調(diào)用者提供盡可能多的信息,這樣他們就可以避免異?;蛘吒菀椎靥幚懋惓?。

因此,請確保在Javadoc中添加一個@throws 聲明,并描述可能導(dǎo)致的異常情況。

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

4. 使用描述性消息拋出異常

這一最佳實踐的理念與前兩個相似。但這一次,你不用給調(diào)用方法的人提供信息。異常消息會被所有人讀取,同時必須了解在日志文件或監(jiān)視工具中報告異常時發(fā)生了什么。

因此,應(yīng)該盡可能準(zhǔn)確地描述問題,并提供相關(guān)的信息來了解異常事件。

別誤會,你不需要寫一段文字,而是應(yīng)該用1-2個簡短的句子解釋異常的原因。這可以幫助開發(fā)團(tuán)隊理解問題的嚴(yán)重性,同時也使你能夠更容易地分析任何服務(wù)事件。

如果拋出一個特定的異常,它的類名很可能已經(jīng)描述了這種類型的錯誤。所以,你不需要提供很多額外的信息。一個很好的例子就是,當(dāng)你以錯誤的格式使用字符串時,如NumberFormatException,它就會被類 java.lang.Long的構(gòu)造函數(shù)拋出。

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

NumberFormatException已經(jīng)告訴你問題的類型,所以只需要提供導(dǎo)致問題的輸入字符串。如果異常類的名稱不具有表達(dá)性,那么就需要提供必要的解釋信息。

17:17:26,386 ERROR TestExceptionHandling:52 - java.lang.NumberFormatException: For input string: "xyz"

5. 最先捕獲特定的異常

大多數(shù)IDE都可以幫助你做到這點,當(dāng)你試圖捕獲不確定的異常時,它會報告一個不可到達(dá)的代碼塊。

問題是只有第一個匹配到異常的catch語句才會被執(zhí)行,所以,如果你最先發(fā)現(xiàn)IllegalArgumentException,你將永遠(yuǎn)不會到達(dá)catch里處理更具體的NumberFormatException,因為它是IllegalArgumentException的一個子類。

所以要首先捕獲特定的異常類,并在末尾添加一些處理不是很具體異常的catch語句。

你可以在下面的代碼片段中看到這樣一個try-catch語句的示例。第一個catch處理所有NumberFormatExceptions異常,第二個catch 處理NumberFormatException異常以外的illegalargumentexception異常。

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

6. 不要在catch中使用Throwable

Throwable 是exceptions 和 errors的父類。當(dāng)然,你可以在catch子句中使用它,但其實你不應(yīng)該這樣做。

如果你在catch子句中使用Throwable,它將不僅捕獲所有的異常,還會捕獲所有錯誤。JVM會拋出錯誤,這是應(yīng)用程序不打算處理的嚴(yán)重問題。典型的例子是 OutOfMemoryError 或 StackOverflowError 。這兩種情況都是由應(yīng)用程序控制之外的情況引起的,無法處理。

所以,最好不要在catch中使用Throwable,除非你完全確定自己處于一個特殊的情況下,并且你需要處理一個錯誤。

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

7. 不要忽略Exceptions

你是否曾經(jīng)分析過只有用例的第一部分才被執(zhí)行的bug報告嗎?

這通常是由一個被忽略的異常引起的。開發(fā)人員可能非常確信它不會被拋出,并添加一個無法處理或無法記錄它的catch語句。當(dāng)你發(fā)現(xiàn)它的時候,你很可能就會明白一句著名的話“This will never happen”。

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

是的,你可能在分析一個不可能發(fā)生的問題。

所以,請千萬不要忽略一個例外。你不會知道代碼在將來會發(fā)生什么變化。有些人可能會刪除阻止異常事件的驗證,而沒有意識到這造成了問題。或者拋出異常的代碼被更改,現(xiàn)在拋出了同一個類的多個異常,而調(diào)用的代碼并不能阻止所有這些異常。
你至少應(yīng)該寫一個日志信息,告訴每個人,需要檢查一下這個問題。

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

8. 不要記錄和拋出一個異常

這可能是最常被忽略的。你可以在許多代碼片段或者庫文件里發(fā)現(xiàn),有異常會被捕獲、記錄和重新拋出。

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

當(dāng)它發(fā)生時記錄一個異常,然后重新拋出它,以便調(diào)用者能夠適當(dāng)?shù)靥幚硭@可能會很直觀。但是它會為同一個異常寫多個錯誤消息。

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)

不添加任何額外的信息。正如在上述第4個中所解釋的那樣,異常消息應(yīng)該描述異常事件。堆棧會告訴你在哪個類、方法和行中異常被拋出。

如果你需要添加額外的信息,應(yīng)該捕獲異常并將其包裝在一個自定義的信息中。但要確保遵循下面的第9條。

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

因此,只需要捕獲一個你想要處理的異常,在方法中指定它,并讓調(diào)用者處理它。

9. 包裝異常

有時最好捕獲一個標(biāo)準(zhǔn)異常并將其封裝到一個定制的異常中。此類異常的典型例子是應(yīng)用程序或框架特定的業(yè)務(wù)異常。這允許你添加額外的信息,并且也可以為異常類實現(xiàn)一個特殊的處理。

當(dāng)你這樣做時,確保引用原始的異常處理。Exception類提供了一些特定的構(gòu)造函數(shù)方法,這些方法可以接受Throwable作為參數(shù)。否則,你將丟失原始異常的堆棧跟蹤和消息,這將使你很難分析導(dǎo)致異常的事件。

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

總結(jié)

正如你所看到的,在拋出或捕獲異常時,有許多不同的事情需要考慮。以上大多數(shù)方法都可以提高代碼可讀性或API可用性。異常通常是一個錯誤處理機(jī)制和一個通信媒介。因此,你應(yīng)該確保同事一起討論想要應(yīng)用的最佳實踐和方法,以便每個人都理解通用概念并以相同的方式使用它們。

以上就是本文關(guān)于Java編程異常處理最佳實踐的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:Java編程中的檢查型異常與非檢查型異常分析、Java多線程之線程通信生產(chǎn)者消費(fèi)者模式及等待喚醒機(jī)制代碼詳解等,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!

相關(guān)文章

  • springcloud使用feign調(diào)用服務(wù)時參數(shù)內(nèi)容過大問題

    springcloud使用feign調(diào)用服務(wù)時參數(shù)內(nèi)容過大問題

    這篇文章主要介紹了springcloud使用feign調(diào)用服務(wù)時參數(shù)內(nèi)容過大問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java程序常見異常及處理匯總

    Java程序常見異常及處理匯總

    這篇文章主要介紹了java程序常見異常及處理匯總,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10
  • MyBatis集成Spring流程詳解

    MyBatis集成Spring流程詳解

    在實際開發(fā)中不僅僅是要展示數(shù)據(jù),還要構(gòu)成數(shù)據(jù)模型添加數(shù)據(jù),這篇文章主要介紹了SpringBoot集成Mybatis操作數(shù)據(jù)庫,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • Java數(shù)據(jù)結(jié)構(gòu)之順序表的實現(xiàn)

    Java數(shù)據(jù)結(jié)構(gòu)之順序表的實現(xiàn)

    線性表(linear?list)是n個具有相同特性的數(shù)據(jù)元素的有限序列。?線性表是一種在實際中廣泛使用的數(shù)據(jù)結(jié)構(gòu),本文將用Java實現(xiàn)順序表,感興趣的可以了解一下
    2022-09-09
  • java實現(xiàn)液晶數(shù)字字體顯示當(dāng)前時間

    java實現(xiàn)液晶數(shù)字字體顯示當(dāng)前時間

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)液晶數(shù)字字體顯示當(dāng)前時間,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • IntelliJ IDEA下SpringBoot如何指定某一個配置文件啟動項目

    IntelliJ IDEA下SpringBoot如何指定某一個配置文件啟動項目

    這篇文章主要介紹了IntelliJ IDEA下SpringBoot如何指定某一個配置文件啟動項目問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Java虛擬機(jī)JVM性能優(yōu)化(二):編譯器

    Java虛擬機(jī)JVM性能優(yōu)化(二):編譯器

    這篇文章主要介紹了Java虛擬機(jī)JVM性能優(yōu)化(二):編譯器,本文先是講解了不同種類的編譯器,并對客戶端編譯,服務(wù)器端編譯器和多層編譯的運(yùn)行性能進(jìn)行了對比,然后給出了幾種常見的JVM優(yōu)化方法,需要的朋友可以參考下
    2014-09-09
  • Java中獲取類路徑classpath的簡單方法(推薦)

    Java中獲取類路徑classpath的簡單方法(推薦)

    下面小編就為大家?guī)硪黄狫ava中獲取類路徑classpath的簡單方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • java 字符串截取的三種方法(推薦)

    java 字符串截取的三種方法(推薦)

    下面小編就為大家?guī)硪黄猨ava 字符串截取的三種方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-11-11
  • Java 創(chuàng)建線程的兩個方法詳解及實例

    Java 創(chuàng)建線程的兩個方法詳解及實例

    這篇文章主要介紹了Java 創(chuàng)建線程的兩個方法詳解及實例的相關(guān)資料,需要的朋友可以參考下
    2017-03-03

最新評論