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

關(guān)于Java異常處理的幾條建議_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

 更新時(shí)間:2017年06月16日 10:36:28   作者:skywang12345  
Java提供了拋出異常、捕捉異常和finally語(yǔ)句的使用來(lái)處理程序異常,下面就來(lái)具體看一下關(guān)于Java異常處理的幾條建議

第1條: 只針對(duì)不正常的情況才使用異常

建議:異常只應(yīng)該被用于不正常的條件,它們永遠(yuǎn)不應(yīng)該被用于正常的控制流。

通過(guò)比較下面的兩份代碼進(jìn)行說(shuō)明。

代碼1

try {
  int i=0;
  while (true) {
    arr[i]=0;
    i++;
  }
} catch (IndexOutOfBoundsException e) {
}

代碼2

for (int i=0; i<arr.length; i++) {
  arr[i]=0;
}

兩份代碼的作用都是遍歷arr數(shù)組,并設(shè)置數(shù)組中每一個(gè)元素的值為0。代碼1的是通過(guò)異常來(lái)終止,看起來(lái)非常難懂,代碼2是通過(guò)數(shù)組邊界來(lái)終止。我們應(yīng)該避免使用代碼1這種方式,主要原因有三點(diǎn):

  1.  異常機(jī)制的設(shè)計(jì)初衷是用于不正常的情況,所以很少會(huì)會(huì)JVM實(shí)現(xiàn)試圖對(duì)它們的性能進(jìn)行優(yōu)化。所以,創(chuàng)建、拋出和捕獲異常的開銷是很昂貴的。
  2.  把代碼放在try-catch中返回阻止了JVM實(shí)現(xiàn)本來(lái)可能要執(zhí)行的某些特定的優(yōu)化。
  3.  對(duì)數(shù)組進(jìn)行遍歷的標(biāo)準(zhǔn)模式并不會(huì)導(dǎo)致冗余的檢查,有些現(xiàn)代的JVM實(shí)現(xiàn)會(huì)將它們優(yōu)化掉。

實(shí)際上,基于異常的模式比標(biāo)準(zhǔn)模式要慢得多。測(cè)試代碼如下:

public class Advice1 {

  private static int[] arr = new int[]{1,2,3,4,5};
  private static int SIZE = 10000;

  public static void main(String[] args) {

    long s1 = System.currentTimeMillis();
    for (int i=0; i<SIZE; i++)
      endByRange(arr);
    long e1 = System.currentTimeMillis();
    System.out.println("endByRange time:"+(e1-s1)+"ms" );

    long s2 = System.currentTimeMillis();
    for (int i=0; i<SIZE; i++)
      endByException(arr);
    long e2 = System.currentTimeMillis();
    System.out.println("endByException time:"+(e2-s2)+"ms" );
  }

  // 遍歷arr數(shù)組: 通過(guò)異常的方式
  private static void endByException(int[] arr) {
    try {
      int i=0;
      while (true) {
        arr[i]=0;
        i++;
        //System.out.println("endByRange: arr["+i+"]="+arr[i]);
      }
    } catch (IndexOutOfBoundsException e) {
    }
  }

  // 遍歷arr數(shù)組: 通過(guò)邊界的方式
  private static void endByRange(int[] arr) {
    for (int i=0; i<arr.length; i++) {
      arr[i]=0;
      //System.out.println("endByException: arr["+i+"]="+arr[i]);
    }
  }
}

運(yùn)行結(jié)果:

endByRange time:8ms
endByException time:16ms

結(jié)果說(shuō)明:通過(guò)異常遍歷的速度比普通方式遍歷數(shù)組慢很多!

第2條: 對(duì)于可恢復(fù)的條件使用被檢查的異常,對(duì)于程序錯(cuò)誤使用運(yùn)行時(shí)異常

  1.  運(yùn)行時(shí)異常     -- RuntimeException類及其子類都被稱為運(yùn)行時(shí)異常。
  2.  被檢查的異常 -- Exception類本身,以及Exception的子類中除了"運(yùn)行時(shí)異常"之外的其它子類都屬于被檢查異常。

它們的區(qū)別是:Java編譯器會(huì)對(duì)"被檢查的異常"進(jìn)行檢查,而對(duì)"運(yùn)行時(shí)異常"不會(huì)檢查。也就是說(shuō),對(duì)于被檢查的異常,要么通過(guò)throws進(jìn)行聲明拋出,要么通過(guò)try-catch進(jìn)行捕獲處理,否則不能通過(guò)編譯。而對(duì)于運(yùn)行時(shí)異常,倘若既"沒(méi)有通過(guò)throws聲明拋出它",也"沒(méi)有用try-catch語(yǔ)句捕獲它",還是會(huì)編譯通過(guò)。當(dāng)然,雖說(shuō)Java編譯器不會(huì)檢查運(yùn)行時(shí)異常,但是,我們同樣可以通過(guò)throws對(duì)該異常進(jìn)行說(shuō)明,或通過(guò)try-catch進(jìn)行捕獲。

ArithmeticException(例如,除數(shù)為0),IndexOutOfBoundsException(例如,數(shù)組越界)等都屬于運(yùn)行時(shí)異常。對(duì)于這種異常,我們應(yīng)該通過(guò)修改代碼進(jìn)行避免它的產(chǎn)生。而對(duì)于被檢查的異常,則可以通過(guò)處理讓程序恢復(fù)運(yùn)行。例如,假設(shè)因?yàn)橐粋€(gè)用戶沒(méi)有存儲(chǔ)足夠數(shù)量的前,所以他在企圖在一個(gè)收費(fèi)電話上進(jìn)行呼叫就會(huì)失?。挥谑蔷蛯⒁粋€(gè)被檢查異常拋出。

第3條: 避免不必要的使用被檢查的異常

"被檢查的異常"是Java語(yǔ)言的一個(gè)很好的特性。與返回代碼不同,"被檢查的異常"會(huì)強(qiáng)迫程序員處理例外的條件,大大提高了程序的可靠性。

但是,過(guò)分使用被檢查異常會(huì)使API用起來(lái)非常不方便。如果一個(gè)方法拋出一個(gè)或多個(gè)被檢查的異常,那么調(diào)用該方法的代碼則必須在一個(gè)或多個(gè)catch語(yǔ)句塊中處理這些異常,或者必須通過(guò)throws聲明拋出這些異常。 無(wú)論是通過(guò)catch處理,還是通過(guò)throws聲明拋出,都給程序員添加了不可忽略的負(fù)擔(dān)。

適用于"被檢查的異常"必須同時(shí)滿足兩個(gè)條件:第一,即使正確使用API并不能阻止異常條件的發(fā)生。第二,一旦產(chǎn)生了異常,使用API的程序員可以采取有用的動(dòng)作對(duì)程序進(jìn)行處理

第4條: 盡量使用標(biāo)準(zhǔn)的異常

代碼重用是值得提倡的,這是一條通用規(guī)則,異常也不例外。重用現(xiàn)有的異常有幾個(gè)好處:

第一,它使得你的API更加易于學(xué)習(xí)和使用,因?yàn)樗c程序員原來(lái)已經(jīng)熟悉的習(xí)慣用法是一致的。

第二,對(duì)于用到這些API的程序而言,它們的可讀性更好,因?yàn)樗鼈儾粫?huì)充斥著程序員不熟悉的異常。

第三,異常類越少,意味著內(nèi)存占用越小,并且轉(zhuǎn)載這些類的時(shí)間開銷也越小。

雖然它們是Java平臺(tái)庫(kù)迄今為止最常被重用的異常,但是,在許可的條件下,其它的異常也可以被重用。例如,如果你要實(shí)現(xiàn)諸如復(fù)數(shù)或者矩陣之類的算術(shù)對(duì)象,那么重用ArithmeticException和NumberFormatException將是非常合適的。如果一個(gè)異常滿足你的需要,則不要猶豫,使用就可以,不過(guò)你一定要確保拋出異常的條件與該異常的文檔中描述的條件一致。這種重用必須建立在語(yǔ)義的基礎(chǔ)上,而不是名字的基礎(chǔ)上!

最后,一定要清楚,選擇重用哪一種異常并沒(méi)有必須遵循的規(guī)則。例如,考慮紙牌對(duì)象的情形,假設(shè)有一個(gè)用于發(fā)牌操作的方法,它的參數(shù)(handSize)是發(fā)一手牌的紙牌張數(shù)。假設(shè)調(diào)用者在這個(gè)參數(shù)中傳遞的值大于整副牌的剩余張數(shù)。那么這種情形既可以被解釋為IllegalArgumentException(handSize的值太大),也可以被解釋為IllegalStateException(相對(duì)客戶的請(qǐng)求而言,紙牌對(duì)象的紙牌太少)。

第5條: 拋出的異常要適合于相應(yīng)的抽象

如果一個(gè)方法拋出的異常與它執(zhí)行的任務(wù)沒(méi)有明顯的關(guān)聯(lián)關(guān)系,這種情形會(huì)讓人不知所措。當(dāng)一個(gè)方法傳遞一個(gè)由低層抽象拋出的異常時(shí),往往會(huì)發(fā)生這種情況。這種情況發(fā)生時(shí),不僅讓人困惑,而且也"污染"了高層API。

為了避免這個(gè)問(wèn)題,高層實(shí)現(xiàn)應(yīng)該捕獲低層的異常,同時(shí)拋出一個(gè)可以按照高層抽象進(jìn)行介紹的異常。這種做法被稱為"異常轉(zhuǎn)譯(exception translation)"。

例如,在Java的集合框架AbstractSequentialList的get()方法如下(基于JDK1.7.0_40):

public E get(int index) {
  try {
    return listIterator(index).next();
  } catch (NoSuchElementException exc) {
    throw new IndexOutOfBoundsException("Index: "+index);
  }
}

listIterator(index)會(huì)返回ListIterator對(duì)象,調(diào)用該對(duì)象的next()方法可能會(huì)拋出NoSuchElementException異常。而在get()方法中,拋出NoSuchElementException異常會(huì)讓人感到困惑。所以,get()對(duì)NoSuchElementException進(jìn)行了捕獲,并拋出了IndexOutOfBoundsException異常。即,相當(dāng)于將NoSuchElementException轉(zhuǎn)譯成了IndexOutOfBoundsException異常。

第6條: 每個(gè)方法拋出的異常都要有文檔

要單獨(dú)的聲明被檢查的異常,并且利用Javadoc的@throws標(biāo)記,準(zhǔn)確地記錄下每個(gè)異常被拋出的條件。

如果一個(gè)類中的許多方法處于同樣的原因而拋出同一個(gè)異常,那么在該類的文檔注釋中對(duì)這個(gè)異常做文檔,而不是為每個(gè)方法單獨(dú)做文檔,這是可以接受的。

第7條: 在細(xì)節(jié)消息中包含失敗 -- 捕獲消息

簡(jiǎn)而言之,當(dāng)我們自定義異?;蛘邟伋霎惓r(shí),應(yīng)該包含失敗相關(guān)的信息。

當(dāng)一個(gè)程序由于一個(gè)未被捕獲的異常而失敗的時(shí)候,系統(tǒng)會(huì)自動(dòng)打印出該異常的棧軌跡。在棧軌跡中包含該異常的字符串表示。典型情況下它包含該異常類的類名,以及緊隨其后的細(xì)節(jié)消息。

第8條: 努力使失敗保持原子性

當(dāng)一個(gè)對(duì)象拋出一個(gè)異常之后,我們總期望這個(gè)對(duì)象仍然保持在一種定義良好的可用狀態(tài)之中。對(duì)于被檢查的異常而言,這尤為重要,因?yàn)檎{(diào)用者通常期望從被檢查的異常中恢復(fù)過(guò)來(lái)。

一般而言,一個(gè)失敗的方法調(diào)用應(yīng)該保持使對(duì)象保持在"它在被調(diào)用之前的狀態(tài)"。具有這種屬性的方法被稱為具有"失敗原子性(failure atomic)"??梢岳斫鉃?,失敗了還保持著原子性。對(duì)象保持"失敗原子性"的方式有幾種:

(01) 設(shè)計(jì)一個(gè)非可變對(duì)象。

(02) 對(duì)于在可變對(duì)象上執(zhí)行操作的方法,獲得"失敗原子性"的最常見(jiàn)方法是,在執(zhí)行操作之前檢查參數(shù)的有效性。如下(Stack.java中的pop方法):

public Object pop() {
  if (size==0)
    throw new EmptyStackException();
  Object result = elements[--size];
  elements[size] = null;
  return result;
}

(03) 與上一種方法類似,可以對(duì)計(jì)算處理過(guò)程調(diào)整順序,使得任何可能會(huì)失敗的計(jì)算部分都發(fā)生在對(duì)象狀態(tài)被修改之前。 

(04) 編寫一段恢復(fù)代碼,由它來(lái)解釋操作過(guò)程中發(fā)生的失敗,以及使對(duì)象回滾到操作開始之前的狀態(tài)上。

(05) 在對(duì)象的一份臨時(shí)拷貝上執(zhí)行操作,當(dāng)操作完成之后再把臨時(shí)拷貝中的結(jié)果復(fù)制給原來(lái)的對(duì)象。
雖然"保持對(duì)象的失敗原子性"是期望目標(biāo),但它并不總是可以做得到。例如,如果多個(gè)線程企圖在沒(méi)有適當(dāng)?shù)耐綑C(jī)制的情況下,并發(fā)的訪問(wèn)一個(gè)對(duì)象,那么該對(duì)象就有可能被留在不一致的狀態(tài)中。

即使在可以實(shí)現(xiàn)"失敗原子性"的場(chǎng)合,它也不是總被期望的。對(duì)于某些操作,它會(huì)顯著的增加開銷或者復(fù)雜性。

總的規(guī)則是:作為方法規(guī)范的一部分,任何一個(gè)異常都不應(yīng)該改變對(duì)象調(diào)用該方法之前的狀態(tài),如果這條規(guī)則被違反,則API文檔中應(yīng)該清楚的指明對(duì)象將會(huì)處于什么樣的狀態(tài)。

第9條: 不要忽略異常

當(dāng)一個(gè)API的設(shè)計(jì)者聲明一個(gè)方法會(huì)拋出某個(gè)異常的時(shí)候,他們正在試圖說(shuō)明某些事情。所以,請(qǐng)不要忽略它!忽略異常的代碼如下:

try {
  ...
} catch (SomeException e) {
}

空的catch塊會(huì)使異常達(dá)不到應(yīng)有的目的,異常的目的是強(qiáng)迫你處理不正常的條件。忽略一個(gè)異常,就如同忽略一個(gè)火警信號(hào)一樣 -- 若把火警信號(hào)器關(guān)閉了,那么當(dāng)真正的火災(zāi)發(fā)生時(shí),就沒(méi)有人看到火警信號(hào)了。所以,至少catch塊應(yīng)該包含一條說(shuō)明,用來(lái)解釋為什么忽略這個(gè)異常是合適的。

相關(guān)文章

  • 如何在Spring?Boot框架中使用攔截器實(shí)現(xiàn)URL限制

    如何在Spring?Boot框架中使用攔截器實(shí)現(xiàn)URL限制

    在Spring?Boot框架中,您可以使用攔截器(Interceptor)來(lái)控制限制URL列表,本文通過(guò)一個(gè)簡(jiǎn)單的示例給大家介紹Spring?Boot?攔截器實(shí)現(xiàn)URL限制的操作方法,感興趣的朋友跟隨小編一起看看吧
    2023-08-08
  • 一篇文章帶你使用SpringBoot基于WebSocket的在線群聊實(shí)現(xiàn)

    一篇文章帶你使用SpringBoot基于WebSocket的在線群聊實(shí)現(xiàn)

    這篇文章主要介紹了一篇文章帶你使用SpringBoot基于WebSocket的在線群聊實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • SpringBoot去除內(nèi)嵌tomcat的實(shí)現(xiàn)

    SpringBoot去除內(nèi)嵌tomcat的實(shí)現(xiàn)

    這篇文章主要介紹了SpringBoot去除內(nèi)嵌tomcat的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • SpringBoot整合Gson 整合Fastjson的實(shí)例詳解

    SpringBoot整合Gson 整合Fastjson的實(shí)例詳解

    這篇文章主要介紹了SpringBoot整合Gson 整合Fastjson的實(shí)例詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • Java中單例模式詳解

    Java中單例模式詳解

    這篇文章主要介紹了Java中單例模式詳解,單例模式包括了懶漢式單例、餓漢式單例、登記式單例三種,想要了解的朋友可以了解一下。
    2016-11-11
  • SpringAOP中的通知Advice詳解

    SpringAOP中的通知Advice詳解

    這篇文章主要介紹了SpringAOP中的通知Advice詳解,Spring 的 AOP 功能中一個(gè)關(guān)鍵概念是通知Advice與切點(diǎn)Pointcut表達(dá)式相關(guān)聯(lián)在特定節(jié)點(diǎn)織入一些邏輯,Spring 提供了五種類型的通知,需要的朋友可以參考下
    2023-08-08
  • Springboot如何優(yōu)雅地進(jìn)行字段校驗(yàn)

    Springboot如何優(yōu)雅地進(jìn)行字段校驗(yàn)

    這篇文章主要給大家介紹了關(guān)于Springboot如何優(yōu)雅地進(jìn)行字段校驗(yàn)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • java多態(tài)注意項(xiàng)小結(jié)

    java多態(tài)注意項(xiàng)小結(jié)

    面向?qū)ο蟮娜筇匦裕悍庋b、繼承、多態(tài)。從一定角度來(lái)看,封裝和繼承幾乎都是為多態(tài)而準(zhǔn)備的。今天通過(guò)本文給大家介紹java多態(tài)注意項(xiàng)總結(jié),感興趣的朋友一起看看吧
    2021-10-10
  • 實(shí)例講解Java的Spring框架中的控制反轉(zhuǎn)和依賴注入

    實(shí)例講解Java的Spring框架中的控制反轉(zhuǎn)和依賴注入

    這篇文章主要介紹了Java的Spring框架中的控制反轉(zhuǎn)和依賴注入,Spring是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下
    2016-02-02
  • java應(yīng)用cpu飆升(超過(guò)100%)故障排查步驟

    java應(yīng)用cpu飆升(超過(guò)100%)故障排查步驟

    在Java并發(fā)編程計(jì)算密集型要進(jìn)行大量的計(jì)算、邏輯判斷等操作,消耗CPU資源,比如計(jì)算圓周率、對(duì)視頻進(jìn)行高清解碼等等,下面這篇文章主要給大家介紹了關(guān)于java應(yīng)用cpu飆升(超過(guò)100%)故障排查步驟的相關(guān)資料,需要的朋友可以參考下
    2023-06-06

最新評(píng)論