<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異常處理和設(shè)計

          共 12826字,需瀏覽 26分鐘

           ·

          2021-04-11 21:26

          在程序設(shè)計中,進(jìn)行異常處理是非常關(guān)鍵和重要的一部分。一個程序的異常處理框架的好壞直接影響到整個項(xiàng)目的代碼質(zhì)量以及后期維護(hù)成本和難度。試想一下,如果一個項(xiàng)目從頭到尾沒有考慮過異常處理,當(dāng)程序出錯從哪里尋找出錯的根源?但是如果一個項(xiàng)目異常處理設(shè)計地過多,又會嚴(yán)重影響到代碼質(zhì)量以及程序的性能。因此,如何高效簡潔地設(shè)計異常處理是一門藝術(shù),本文下面先講述Java異常機(jī)制最基礎(chǔ)的知識,然后給出在進(jìn)行Java異常處理設(shè)計時的幾個建議。

          若有不正之處,請多多諒解和指正,不勝感激。

          請尊重作者勞動成果,轉(zhuǎn)載請標(biāo)明轉(zhuǎn)載地址:http://www.cnblogs.com/dolphin0520/p/3769804.html

          以下是本文的目錄大綱:

          • 一.什么是異常

          • Java中如何處理異常

          • 深刻理解try,catch,finally,throws,throw五個關(guān)鍵字

          • 在類繼承的時候,方法覆蓋時如何進(jìn)行異常拋出聲明

          • 異常處理和設(shè)計的幾個建議

          一.什么是異常

          異常的英文單詞是exception,字面翻譯就是“意外、例外”的意思,也就是非正常情況。通過異常機(jī)制,我們可以更好地提升程序的健壯性。

          在Java中異常被當(dāng)做對象來處理,根類是java.lang.Throwable類,在Java中定義了很多異常類(如OutOfMemoryError、NullPointerException、IndexOutOfBoundsException等),這些異常類分為兩大類:Error和Exception。

          Error用于指示合理的應(yīng)用程序不應(yīng)該試圖捕獲的嚴(yán)重問題,這種情況是很大的問題,大到你無法處理,是無法處理的異常,因此可以不用管它。比如OutOfMemoryError,斷電、斷網(wǎng)、服務(wù)器宕機(jī)等,一般發(fā)生這種異常,JVM會選擇終止程序。因此我們編寫程序時不需要關(guān)心這類異常。

          Exception,也就是我們經(jīng)常見到的一些異常情況,比如NullPointerException、IndexOutOfBoundsException,這些異常是我們可以處理的異常。

          Exception類的異常包括checked exception和unchecked exception(unchecked exception也稱運(yùn)行時異常RuntimeException。

          unchecked exception(非檢查異常),也稱運(yùn)行時異常(RuntimeException),比如常見的NullPointerException、IndexOutOfBoundsException、ArithmeticException(算術(shù)異常)、ClassCastException(類型強(qiáng)制轉(zhuǎn)換異常)等。對于運(yùn)行時異常,java編譯器不要求必須進(jìn)行異常捕獲處理或者拋出聲明,由程序員自行決定,即也可以使用try..catch...塊顯示捕獲處理,或者顯示拋出。

          checked exception(檢查異常),也稱非運(yùn)行時異常(運(yùn)行時異常以外的異常就是非運(yùn)行時異常),java編譯器強(qiáng)制程序員必須進(jìn)行捕獲處理或者顯示拋出,比如常見的IOExeption和SQLException。對于非運(yùn)行時異常如果不進(jìn)行捕獲或者拋出聲明處理,編譯都不會通過。

          在Java中,異常類的結(jié)構(gòu)層次圖如下圖所示:

          在Java中,所有異常類的父類是Throwable類(java.lang包下),Error類是error類型異常的父類,Exception類是exception類型異常的父類,RuntimeException類是所有運(yùn)行時異常的父類,RuntimeException以外的并且繼承Exception的類是非運(yùn)行時異常。

          典型的RuntimeException包括NullPointerException、IndexOutOfBoundsException、IllegalArgumentException(非法參數(shù)異常)等。

          典型的非RuntimeException包括IOException、SQLException等。

          二.Java中如何處理異常

          在Java中如果需要處理異常,必須先對異常進(jìn)行捕獲,然后再對異常情況進(jìn)行處理。如何對可能發(fā)生異常的代碼進(jìn)行異常捕獲和處理呢?使用try和catch關(guān)鍵字即可,如下面一段代碼所示:

          try {
          File file =new File("d:/a.txt");
          if(!file.exists())
          file.createNewFile();
          } catch(IOException e) {
          // TODO: handle exception
          }

          被try塊包圍的代碼說明這段代碼可能會發(fā)生異常,一旦發(fā)生異常,異常便會被catch捕獲到,然后需要在catch塊中進(jìn)行異常處理。

          這是一種處理異常的方式。在Java中還提供了另一種異常處理方式即拋出異常,顧名思義,也就是說一旦發(fā)生異常,我把這個異常拋出去,讓調(diào)用者去進(jìn)行處理,自己不進(jìn)行具體的處理,此時需要用到throw和throws關(guān)鍵字。 

          下面看一個示例:

          public class Main {
          publicstatic void main(String[] args) {
          try{
          createFile();
          }catch (Exception e) {
          // TODO: handle exception
          }
          }

          publicstatic void createFile() throws IOException{
          File file =new File("d:/a.txt");
          if(!file.exists())
          file.createNewFile();
          }
          }

          這段代碼和上面一段代碼的區(qū)別是,在實(shí)際的createFile方法中并沒有捕獲異常,而是用throws關(guān)鍵字聲明拋出異常,即告知這個方法的調(diào)用者此方法可能會拋出IOException。那么在main方法中調(diào)用createFile方法的時候,采用try...catch塊進(jìn)行了異常捕獲處理。

          當(dāng)然還可以采用throw關(guān)鍵字手動來拋出異常對象。下面看一個例子:

          public class Main {
          publicstatic void main(String[] args) {
          try{
          int[] data =new int[]{1,2,3};
          System.out.println(getDataByIndex(-1,data));
          }catch (Exception e) {
          System.out.println(e.getMessage());
          }

          }

          publicstatic int getDataByIndex(int index,int[] data)throws Exception {
          if(index<0||index>=data.length)
          thrownew ArrayIndexOutOfBoundsException("數(shù)組下標(biāo)越界");
          returndata[index];
          }
          }

          然后在catch塊中進(jìn)行捕獲。

          也就說在Java中進(jìn)行異常處理的話,對于可能會發(fā)生異常的代碼,可以選擇三種方法來進(jìn)行異常處理:

          1)對代碼塊用try..catch進(jìn)行異常捕獲處理;

          2)在 該代碼的方法簽名處用throws進(jìn)行拋出聲明,告知此方法的調(diào)用者這段代碼可能會出現(xiàn)這些異常,你需要謹(jǐn)慎處理。此時有兩種情況:

          如果聲明拋出的異常是非運(yùn)行時異常,此方法的調(diào)用者必須顯示地用try..catch塊進(jìn)行捕獲或者繼續(xù)向上層拋出異常。

          如果聲明拋出的異常是運(yùn)行時異常,此方法可以用try..catch進(jìn)行異常捕獲處理,也可以不捕獲,此方法無需使用throws聲明拋出;此方法的調(diào)用者可以選擇地進(jìn)行異常捕獲處理,也可不捕獲處理,同樣也可以不使用throws聲明。

          3)在代碼塊用throw手動拋出一個異常對象,此時也有兩種情況,跟2)中的類似:

          如果拋出的異常對象是非運(yùn)行時異常,要么用try..catch進(jìn)行異常捕獲處理,要么放在一個帶throws聲明拋出的方法中,此方法的調(diào)用者必須顯示地用try..catch塊進(jìn)行捕獲或者繼續(xù)向上層拋出異常。

          如果拋出的異常對象是運(yùn)行時異常,此方法可以用try..catch進(jìn)行異常捕獲處理,也可以不捕獲,此方法無需使用throws聲明拋出;此方法的調(diào)用者可以選擇地進(jìn)行異常捕獲處理也可不捕獲處理,同樣也可以不使用throws聲明。(如果最終將異常拋給main方法,則相當(dāng)于交給jvm自動處理,此時jvm會簡單地打印異常信息)

          三.深刻理解try,catch,finally,throws,throw五個關(guān)鍵字

          下面我們來看一下異常機(jī)制中五個關(guān)鍵字的用法以及需要注意的地方。

          1.try,catch,finally

          try關(guān)鍵字用來包圍可能會出現(xiàn)異常的邏輯代碼,它單獨(dú)無法使用,必須配合catch或者finally使用。Java編譯器允許的組合使用形式只有以下三種形式:

          try...catch...;     try....finally......;    try....catch...finally...

          當(dāng)然catch塊可以有多個,注意try塊只能有一個,finally塊是可選的(但是最多只能有一個finally塊)。

          三個塊執(zhí)行的順序?yàn)?:

           try—>catch—>finally。

          當(dāng)然如果沒有發(fā)生異常,則catch塊不會執(zhí)行。但是finally塊無論在什么情況下都是會執(zhí)行的,及時try塊和catch塊中有return語句或throw語句,也會先跳到finally塊執(zhí)行,然后再跳回執(zhí)行return或throw語句,(這點(diǎn)要非常注意,因此部分情況下,都會將釋放資源的操作放在finally塊中進(jìn)行)。因此盡量避免在finally塊中使用return或throw等語句,會導(dǎo)致方法終止,而無法跳回try塊或catch塊執(zhí)行retrun或throw語句。           有一種例外不會執(zhí)行finally塊,就是在try或catch塊中使用了System.exit(0或1);語句,則直接退出程序,finally得不到執(zhí)行。 

          finally塊常用于回收物理資源,如關(guān)閉文件、關(guān)閉數(shù)據(jù)庫連接、關(guān)閉網(wǎng)絡(luò)連接等。

          在有多個catch塊的時候,是按照catch塊的先后順序進(jìn)行匹配的,一旦異常類型被一個catch塊匹配,則不會與后面的catch塊進(jìn)行匹配,因此小范圍的異常類型應(yīng)該放在前面,大異常范圍的應(yīng)該放在后面(后者小異常的catch不會得到執(zhí)行,導(dǎo)致編譯器報錯)。

          在使用try..catch..finally塊的時候,注意千萬不要在finally塊中使用return,因?yàn)閒inally中的return會覆蓋已有的返回值。下面看一個例子:

          import java.io.FileInputStream;
          import java.io.FileNotFoundException;
          import java.io.IOException;


          public class Main {
          publicstatic void main(String[] args) {
          String str =new Main().openFile();
          System.out.println(str);

          }

          publicString openFile() {
          try{
          FileInputStream inputStream =new FileInputStream("d:/a.txt");
          intch = inputStream.read();
          System.out.println("aaa");
          return"step1";
          }catch (FileNotFoundException e) {
          System.out.println("file not found");
          return"step2";
          }catch(IOException e) {
          System.out.println("io exception");
          return"step3";
          }finally{
          System.out.println("finally block");
          //return "finally";
          }
          }
          }

          這段程序的輸出結(jié)果為:

          可以看出,在try塊中發(fā)生FileNotFoundException之后,就跳到第一個catch塊,打印"file not found"信息,遇到return語句,跳到finally塊執(zhí)行,執(zhí)行完后跳回return語句將"step2"賦值給返回值,將返回值返回。

          從這個例子說明,無論try塊或者catch塊中是否包含return語句,都會執(zhí)行finally塊。

          如果將這個程序稍微修改一下,將finally塊中的return語句注釋去掉,運(yùn)行結(jié)果是:

          最后打印出的是"finally",返回值被重新覆蓋了。

          因此如果方法有返回值,切忌不要再finally中使用return,這樣會使得程序結(jié)構(gòu)變得混亂。

          2.throws和thow關(guān)鍵字

          throws拋出的是異常類型(表明方法可能會拋出的異常類型),throw拋出的是異常對象(實(shí)例)

          1)throws出現(xiàn)在方法的聲明中,表示該方法可能會拋出的異常,然后交給上層調(diào)用它的方法程序處理,允許throws后面跟著多個異常類型,使用英文逗號隔開;

          2)一般會用于程序出現(xiàn)某種邏輯時程序員主動拋出某種特定類型的異常。throw只會出現(xiàn)在方法體中,當(dāng)方法在執(zhí)行過程中遇到異常情況時,將異常信息封裝為異常對象,然后throw出去。throw關(guān)鍵字的一個非常重要的作用就是異常類型的轉(zhuǎn)換(會在后面闡述道)。

          throws表示出現(xiàn)異常的一種可能性,并不一定會發(fā)生這些異常;throw則是拋出了異常,執(zhí)行throw則一定拋出了某種異常對象。兩者都是消極處理異常的方式(這里的消極并不是說這種方式不好),只是拋出或者可能拋出異常,但是不會由方法去處理異常,真正的處理異常由此方法的上層調(diào)用處理。

          四.在類繼承的時候,方法覆蓋時如何進(jìn)行異常拋出聲明

           本小節(jié)討論子類重寫父類方法的時候,如何確定異常拋出聲明的類型。下面是三點(diǎn)原則:

          1)父類的方法沒有聲明異常,子類在重寫該方法的時候不能聲明異常;

          2)如果父類的方法聲明一個異常exception1,則子類在重寫該方法的時候聲明的異常不能是exception1的父類,即子類重寫的方法拋出的異常范圍不能比父類大;

          3)如果父類的方法聲明的異常類型只有非運(yùn)行時異常(或運(yùn)行時異常),則子類在重寫該方法的時候聲明的異常也只能有非運(yùn)行時異常(或運(yùn)行時異常),不能含有運(yùn)行時異常(非運(yùn)行時異常)。

          五、Throwable類中的常用方法

          注意:catch關(guān)鍵字后面括號中的Exception類型的參數(shù)e。Exception就是try代碼塊傳遞給catch代碼塊的變量類型,e就是變量名。catch代碼塊中語句"e.getMessage();"用于輸出錯誤性質(zhì)。通常異常處理常用3個函數(shù)來獲取異常的有關(guān)信息:

          getCause():返回拋出異常的原因。如果 cause 不存在或未知,則返回 null。

          getMeage():返回異常的消息信息。

          printStackTrace():對象的堆棧跟蹤輸出至錯誤輸出流,作為字段 System.err 的值。

          有時為了簡單會忽略掉catch語句后的代碼,這樣try-catch語句就成了一種擺設(shè),一旦程序在運(yùn)行過程中出現(xiàn)了異常,就會忽略處理異常,而錯誤發(fā)生的原因很難查找。

          六、java常見的異常

          在Java中提供了一些異常用來描述經(jīng)常發(fā)生的錯誤,對于這些異常,有的需要程序員進(jìn)行捕獲處理或聲明拋出,有的是由Java虛擬機(jī)自動進(jìn)行捕獲處理。Java中常見的異常類:

          1. runtimeException子類:

          1、 java.lang.ArrayIndexOutOfBoundsException
          數(shù)組索引越界異常。當(dāng)對數(shù)組的索引值為負(fù)數(shù)或大于等于數(shù)組大小時拋出。
          2、java.lang.ArithmeticException
          算術(shù)條件異常。譬如:整數(shù)除零等。
          3、java.lang.NullPointerException
          空指針異常。當(dāng)應(yīng)用試圖在要求使用對象的地方使用了null時,拋出該異常。譬如:調(diào)用null對象的實(shí)例方法、訪問null對象的屬性、計算null對象的長度、使用throw語句拋出null等等
          4、java.lang.ClassNotFoundException
          找不到類異常。當(dāng)應(yīng)用試圖根據(jù)字符串形式的類名構(gòu)造類,而在遍歷CLASSPAH之后找不到對應(yīng)名稱的class文件時,拋出該異常。
          5、java.lang.NegativeArraySizeException 數(shù)組長度為負(fù)異常

          6、java.lang.ArrayStoreException 數(shù)組中包含不兼容的值拋出的異常

          7、java.lang.SecurityException 安全性異常

          8、java.lang.IllegalArgumentException 非法參數(shù)異常

          2.IOException

          IOException:操作輸入流和輸出流時可能出現(xiàn)的異常。

          EOFException 文件已結(jié)束異常

          FileNotFoundException 文件未找到異常

          3. 其他

          ClassCastException 類型轉(zhuǎn)換異常類

          ArrayStoreException 數(shù)組中包含不兼容的值拋出的異常

          SQLException 操作數(shù)據(jù)庫異常類

          NoSuchFieldException 字段未找到異常

          NoSuchMethodException 方法未找到拋出的異常

          NumberFormatException 字符串轉(zhuǎn)換為數(shù)字拋出的異常

          StringIndexOutOfBoundsException 字符串索引超出范圍拋出的異常

          IllegalAccessException 不允許訪問某類異常

          InstantiationException 當(dāng)應(yīng)用程序試圖使用Class類中的newInstance()方法創(chuàng)建一個類的實(shí)例,而指定的類對象無法被實(shí)例化時,拋出該異常

          七、自定義異常

          自定義異常通常是定義一個繼承自Exception類的子類。一般情況下我們都會直接繼承自Exception類,當(dāng)然也可以自定義運(yùn)行時異常,只需繼承RuntimeException類即可。

          自定義異常時,通常需要提供兩個構(gòu)造器,(1)、一個無參的構(gòu)造器;(2)帶一個字符串參數(shù)的構(gòu)造器,該字符串作為異常對象的描述信息(即異常對象的getMessage()方法的返回值,用于初始化繼承自父類中的message屬性)

          (3)在異常鏈中還需要一種帶一個異常類型參數(shù)的構(gòu)造器,具體介紹見下。

          1、創(chuàng)建自定義異常:

          public class MyException extends Exception{
          public MyException(){
          super();
          }
          public MyException(String msg){
          super(msg);
          }
          }

          2、在類中使用異常:

          public class ExceptionTest {

          public static void execute(String a) throws MyException {
          System.out.println("execute...");
          if("true".equals(a)){
          throw new MyException("參數(shù)不能為 true");
          }
          }
          }

          (3)帶有一個異常類型參數(shù)的構(gòu)造器

          把底層的原始異常直接傳給用戶是一種不負(fù)責(zé)任的表現(xiàn),通常的做法是:程序先捕獲原始異常,然后拋出一個新的業(yè)務(wù)異常,新的業(yè)務(wù)異常中包含了對用戶的提示信息,這種處理方式唄稱為異常轉(zhuǎn)譯。在異常鏈中自定義一個異常類通常還需添加一個構(gòu)造器,構(gòu)造器帶有一個異常類型的參數(shù),該參數(shù)用于初始化從Throwable類繼承的cause對象,這個cause對象用于表示原始異常,使得拋出新的異常,程序員仍然可以通過這個新的異常到原始異常(即異常最初發(fā)生的位置)。

          八、異常鏈(異常轉(zhuǎn)譯)

          把底層的原始異常直接傳給用戶是一種不負(fù)責(zé)任的表現(xiàn),通常的做法是:程序先捕獲原始異常,然后拋出一個新的業(yè)務(wù)異常,新的業(yè)務(wù)異常中包含了對用戶的提示信息,這種處理方式唄稱為異常轉(zhuǎn)譯。在異常鏈中自定義一個異常類通常還需添加一個構(gòu)造器,構(gòu)造器帶有一個異常類型的參數(shù),該參數(shù)用于初始化從Throwable類繼承的cause對象,這個cause對象用于表示原始異常,使得拋出新的異常,程序員仍然可以通過這個新的異常到原始異常(即異常最初發(fā)生的位置)。

          這種把捕獲一個異常然后拋出另一個異常,并把原始異常信息保存下來是一種典型的鏈?zhǔn)教幚?。也被稱為“異常鏈”。

          假如程序需要實(shí)現(xiàn)工資計算的方法

          public calSal() throws SalException
          {
          try
          {
          //實(shí)現(xiàn)結(jié)算工資的業(yè)務(wù)邏輯
          ...
          }
          catch(SQLException sqle)
          {
          //把原始異常記錄下來,留給管理員
          ...
          //下面異常中的message就是對用戶的提示
          throw new SalException("訪問底層數(shù)據(jù)庫出現(xiàn)異常");
          }
          catch(Exception e)
          {
          //把原始異常記錄下來,留給管理員
          ...
          //下面異常中的message就是對用戶的提示
          throw new SalException("系統(tǒng)出現(xiàn)未知異常");
          }
          }

          上面的程序?qū)崿F(xiàn)了異常轉(zhuǎn)譯,從而把原始異常信息隱藏起來,僅向上提供必要的異常提示信息。但是無法追蹤到原始異常了,

          下面通過帶一個異常類型參數(shù)的構(gòu)造器創(chuàng)建異常對象,從而可以將原始異常封裝在新的異常中,便于追蹤原始異常。

          public calSal() throws SalException
          {
          try
          {
          //實(shí)現(xiàn)結(jié)算工資的業(yè)務(wù)邏輯
          ...
          }
          catch(SQLException sqle)
          {
          //把原始異常記錄下來,留給管理員
          ...
          //下面異常中的sql就是原始異常
          throw new SalException(sql);
          }
          catch(Exception e)
          {
          //把原始異常記錄下來,留給管理員
          ...
          //下面異常中的e就是原始異常
          throw new SalException(e);
          }
          }

          public class SalException extends Exception
          {
          public SalException();//無參構(gòu)造器
          /*帶一個字符串參數(shù)的構(gòu)造器,msg用于初始化從父類中繼承的message屬性,
          其是getMessage()的返回值,即該異常的詳細(xì)描述詳細(xì)*/

          public SalException(String msg)
          {
          super(msg);
          }
          /*帶一個異常類型參數(shù)構(gòu)造器,異常對象形參t用于初始化從父類中繼承的cause對象,
          該cause對象用于保存原始異常對象*/

          public SalException(Throwable t)
          {
          super(t);
          }
          }

          九.異常處理和設(shè)計的幾個建議

          以下是根據(jù)前人總結(jié)的一些異常處理的建議:

          1.只在必要使用異常的地方才使用異常,不要用異常去控制程序的流程

          謹(jǐn)慎地使用異常,異常捕獲的代價非常高昂,異常使用過多會嚴(yán)重影響程序的性能。如果在程序中能夠用if語句和Boolean變量來進(jìn)行邏輯判斷,那么盡量減少異常的使用,從而避免不必要的異常捕獲和處理。比如下面這段經(jīng)典的程序:

          public void useExceptionsForFlowControl() {
          try{
          while(true) {
          increaseCount();
          }
          }catch (MaximumCountReachedException ex) {
          }
          //Continue execution
          }

          public void increaseCount() throwsMaximumCountReachedException {
          if(count >= 5000)
          thrownew MaximumCountReachedException();
          }

          上邊的useExceptionsForFlowControl()用一個無限循環(huán)來增加count直到拋出異常,這種做法并沒有說讓代碼不易讀,而是使得程序執(zhí)行效率降低。

          2.切忌使用空catch塊

          在捕獲了異常之后什么都不做,相當(dāng)于忽略了這個異常。千萬不要使用空的catch塊,空的catch塊意味著你在程序中隱藏了錯誤和異常,并且很可能導(dǎo)致程序出現(xiàn)不可控的執(zhí)行結(jié)果。如果你非??隙ú东@到的異常不會以任何方式對程序造成影響,最好用Log日志將該異常進(jìn)行記錄,以便日后方便更新和維護(hù)。

          3.檢查異常和非檢查異常的選擇

          一旦你決定拋出異常,你就要決定拋出什么異常。這里面的主要問題就是拋出檢查異常還是非檢查異常。

          檢查異常導(dǎo)致了太多的try…catch代碼,可能有很多檢查異常對開發(fā)人員來說是無法合理地進(jìn)行處理的,比如SQLException,而開發(fā)人員卻不得不去進(jìn)行try…catch,這樣就會導(dǎo)致經(jīng)常出現(xiàn)這樣一種情況:邏輯代碼只有很少的幾行,而進(jìn)行異常捕獲和處理的代碼卻有很多行。這樣不僅導(dǎo)致邏輯代碼閱讀起來晦澀難懂,而且降低了程序的性能。

          我個人建議盡量避免檢查異常的使用,如果確實(shí)該異常情況的出現(xiàn)很普遍,需要提醒調(diào)用者注意處理的話,就使用檢查異常;否則使用非檢查異常。

          因此,在一般情況下,我覺得盡量將檢查異常轉(zhuǎn)變?yōu)榉菣z查異常交給上層處理。

          4.注意catch塊的順序

          不要把上層類的異常放在最前面的catch塊。比如下面這段代碼:

          try {
          FileInputStream inputStream =new FileInputStream("d:/a.txt");
          intch = inputStream.read();
          System.out.println("aaa");
          return"step1";
          }catch (IOException e) {
             System.out.println("io exception");  
          return"step2";
          }catch(FileNotFoundException e) {
          System.out.println("file not found");    
          return"step3";
          }finally{
          System.out.println("finally block");
          //return "finally";
          }

          第二個catch的FileNotFoundException將永遠(yuǎn)不會被捕獲到,因?yàn)镕ileNotFoundException是IOException的子類。

          5.不要將提供給用戶看的信息放在異常信息里

          比如下面這段代碼:

          public class Main {
          publicstatic void main(String[] args) {
          try{
          String user =null;
          String pwd =null;
          login(user,pwd);
          }catch (Exception e) {
          System.out.println(e.getMessage());
          }

          }

          publicstatic void login(String user,String pwd) {
          if(user==null||pwd==null)
          thrownew NullPointerException("用戶名或者密碼為空");
          //...
          }
          }

          展示給用戶錯誤提示信息最好不要跟程序混淆一起,比較好的方式是將所有錯誤提示信息放在一個配置文件中統(tǒng)一管理。

          6.避免多次在日志信息中記錄同一個異常

          只在異常最開始發(fā)生的地方進(jìn)行日志信息記錄。很多情況下異常都是層層向上拋出的,如果在每次向上拋出的時候,都Log到日志系統(tǒng)中,則會導(dǎo)致無從查找異常發(fā)生的根源。

          7. 異常處理盡量放在高層進(jìn)行

          盡量將異常統(tǒng)一拋給上層調(diào)用者,由上層調(diào)用者統(tǒng)一之時如何進(jìn)行處理。如果在每個出現(xiàn)異常的地方都直接進(jìn)行處理,會導(dǎo)致程序異常處理流程混亂,不利于后期維護(hù)和異常錯誤排查。由上層統(tǒng)一進(jìn)行處理會使得整個程序的流程清晰易懂。

          8. 在finally中釋放資源

          如果有使用文件讀取、網(wǎng)絡(luò)操作以及數(shù)據(jù)庫操作等,記得在finally中釋放資源。這樣不僅會使得程序占用更少的資源,也會避免不必要的由于資源未釋放而發(fā)生的異常情況。 

          推薦閱讀

          面試|return 和finally那些事兒

          一千行 MySQL 學(xué)習(xí)筆記

          沒娛樂、沒性生活,中關(guān)村程序員要被逼瘋了

          瀏覽 61
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  做受 视频毛片丰满 | 久久婷婷五月天人人综合 | 黄色AⅤ电影勉费 | 香蕉网久久 | 免费成人精品 |