亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

老生常談Java異常處理和設(shè)計(推薦)

 更新時間:2017年05月17日 13:41:16   投稿:jingxian  
下面小編就為大家?guī)硪黄仙U凧ava異常處理和設(shè)計(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

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

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

以下是本文的目錄大綱:

一、什么是異常

二、Java中如何處理異常

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

四、在類繼承的時候,方法覆蓋時如何進行異常拋出聲明

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

一、什么是異常     

異常的英文單詞是exception,字面翻譯就是“意外、例外”的意思,也就是非正常情況。事實上,異常本質(zhì)上是程序上的錯誤,包括程序邏輯錯誤和系統(tǒng)錯誤。比如使用空的引用、數(shù)組下標越界、內(nèi)存溢出錯誤等,這些都是意外的情況,背離我們程序本身的意圖。錯誤在我們編寫程序的過程中會經(jīng)常發(fā)生,包括編譯期間和運行期間的錯誤,在編譯期間出現(xiàn)的錯誤有編譯器幫助我們一起修正,然而運行期間的錯誤便不是編譯器力所能及了,并且運行期間的錯誤往往是難以預(yù)料的。假若程序在運行期間出現(xiàn)了錯誤,如果置之不理,程序便會終止或直接導(dǎo)致系統(tǒng)崩潰,顯然這不是我們希望看到的結(jié)果。因此,如何對運行期間出現(xiàn)的錯誤進行處理和補救呢?Java提供了異常機制來進行處理,通過異常機制來處理程序運行期間出現(xiàn)的錯誤。通過異常機制,我們可以更好地提升程序的健壯性。

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

Error是無法處理的異常,比如OutOfMemoryError,一般發(fā)生這種異常,JVM會選擇終止程序。因此我們編寫程序時不需要關(guān)心這類異常。

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

Exception類的異常包括checked exception和unchecked exception(unchecked exception也稱運行時異常RuntimeException,當(dāng)然這里的運行時異常并不是前面我所說的運行期間的異常,只是Java中用運行時異常這個術(shù)語來表示,Exception類的異常都是在運行期間發(fā)生的)。

unchecked exception(非檢查異常),也稱運行時異常(RuntimeException),比如常見的NullPointerException、IndexOutOfBoundsException。對于運行時異常,java編譯器不要求必須進行異常捕獲處理或者拋出聲明,由程序員自行決定。

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

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

在Java中,所有異常類的父類是Throwable類,Error類是error類型異常的父類,Exception類是exception類型異常的父類,RuntimeException類是所有運行時異常的父類,RuntimeException以外的并且繼承Exception的類是非運行時異常。

典型的RuntimeException包括NullPointerException、IndexOutOfBoundsException、IllegalArgumentException等。

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

二、Java中如何處理異常                                                                

在Java中如果需要處理異常,必須先對異常進行捕獲,然后再對異常情況進行處理。如何對可能發(fā)生異常的代碼進行異常捕獲和處理呢?使用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塊中進行異常處理。

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

下面看一個示例:

public class Main {
  public static void main(String[] args) {
    try {
      createFile();
    } catch (Exception e) {
      // TODO: handle exception
    }
  }
   
  public static void createFile() throws IOException{
    File file = new File("d:/a.txt");
    if(!file.exists())
      file.createNewFile();
  }
}

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

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

public class Main {
  public static 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());
    }
     
  }
   
  public static int getDataByIndex(int index,int[] data) {
    if(index<0||index>=data.length)
      throw new ArrayIndexOutOfBoundsException("數(shù)組下標越界");
    return data[index];
  }
}

然后在catch塊中進行捕獲。

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

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

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

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

如果聲明拋出的異常是運行時異常,此方法的調(diào)用者可以選擇地進行異常捕獲處理。

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

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

如果拋出的異常對象是運行時異常,此方法的調(diào)用者可以選擇地進行異常捕獲處理。

(如果最終將異常拋給main方法,則相當(dāng)于交給jvm自動處理,此時jvm會簡單地打印異常信息)

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

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

1.try,catch,finally

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

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

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

三個塊執(zhí)行的順序為try—>catch—>finally。

當(dāng)然如果沒有發(fā)生異常,則catch塊不會執(zhí)行。但是finally塊無論在什么情況下都是會執(zhí)行的(這點要非常注意,因此部分情況下,都會將釋放資源的操作放在finally塊中進行)。

在有多個catch塊的時候,是按照catch塊的先后順序進行匹配的,一旦異常類型被一個catch塊匹配,則不會與后面的catch塊進行匹配。

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

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
 
 
public class Main {
  public static void main(String[] args) {
    String str = new Main().openFile();
    System.out.println(str);
     
  }
   
  public String openFile() {
    try {
      FileInputStream inputStream = new FileInputStream("d:/a.txt");
      int ch = 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"信息,并將"step2"賦值給返回值,然后執(zhí)行finally塊,最后將返回值返回。

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

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

  

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

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

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

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)用處理。

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

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

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

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

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

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

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

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

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

public void useExceptionsForFlowControl() { 
 try { 
 while (true) { 
  increaseCount(); 
  } 
 } catch (MaximumCountReachedException ex) { 
 } 
 //Continue execution 
} 
   
public void increaseCount() throws MaximumCountReachedException { 
 if (count >= 5000) 
  throw new MaximumCountReachedException(); 
}

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

2.切忌使用空catch塊

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

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

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

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

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

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

4.注意catch塊的順序

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

try {
    FileInputStream inputStream = new FileInputStream("d:/a.txt");
    int ch = 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將永遠不會被捕獲到,因為FileNotFoundException是IOException的子類。

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

比如下面這段代碼:

public class Main {
  public static void main(String[] args) {
    try {
      String user = null;
      String pwd = null;
      login(user,pwd);
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
     
  }
   
  public static void login(String user,String pwd) {
    if(user==null||pwd==null)
      throw new NullPointerException("用戶名或者密碼為空");
    //...
  }
}

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

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

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

7. 異常處理盡量放在高層進行

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

8. 在finally中釋放資源

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

以上這篇老生常談Java異常處理和設(shè)計(推薦)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • springboot 集成支付寶支付的示例代碼

    springboot 集成支付寶支付的示例代碼

    這篇文章主要介紹了springboot 集成支付寶支付的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • MyBatis?多表聯(lián)合查詢及優(yōu)化方法

    MyBatis?多表聯(lián)合查詢及優(yōu)化方法

    大家都知道Hibernate 是全自動的數(shù)據(jù)庫持久層框架,它可以通過實體來映射數(shù)據(jù)庫,通過設(shè)置一對多、多對一、一對一、多對多的關(guān)聯(lián)來實現(xiàn)聯(lián)合查詢,接下來通過本文給大家介紹MyBatis?多表聯(lián)合查詢及優(yōu)化,需要的朋友可以參考下
    2022-08-08
  • 解決遇到Cannot resolve ch.qos.logback:logback-classic:1.2.3錯誤的問題

    解決遇到Cannot resolve ch.qos.logback:logback-classic:

    當(dāng)使用Maven配置項目依賴時,可能會遇到無法解析特定版本的錯誤,例如,logback-classic版本1.2.3可能無法在配置的倉庫中找到,解決方法包括檢查倉庫是否包含所需版本,或更新到其他可用版本,可通過Maven官網(wǎng)搜索并找到適用的版本,替換依賴配置中的版本信息
    2024-09-09
  • java 如何判斷是否可以ping通某個地址

    java 如何判斷是否可以ping通某個地址

    這篇文章主要介紹了java 如何判斷是否可以ping通某個地址,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Maven引入本地Jar包并打包進War包中的方法

    Maven引入本地Jar包并打包進War包中的方法

    本篇文章主要介紹了Maven引入本地Jar包并打包進War包中的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • java讀取csv文件和寫csv示例分享

    java讀取csv文件和寫csv示例分享

    這篇文章主要介紹了JAVA對CSV格式文本數(shù)據(jù)處理后再保存成新CSV格式文本的模板,可以學(xué)習(xí)到j(luò)ava讀取csv文件和寫csv的方法,需要的朋友可以參考下
    2014-03-03
  • SpringBoot整合WebSocket的客戶端和服務(wù)端的實現(xiàn)代碼

    SpringBoot整合WebSocket的客戶端和服務(wù)端的實現(xiàn)代碼

    這篇文章主要介紹了SpringBoot整合WebSocket的客戶端和服務(wù)端的實現(xiàn),本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • 啟動Springboot項目時找不到Mapper的問題及解決

    啟動Springboot項目時找不到Mapper的問題及解決

    這篇文章主要介紹了啟動Springboot項目時找不到Mapper的問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • 關(guān)于SpringSecurity配置403權(quán)限訪問頁面的完整代碼

    關(guān)于SpringSecurity配置403權(quán)限訪問頁面的完整代碼

    本文給大家分享SpringSecurity配置403權(quán)限訪問頁面的完整代碼,配置之前和配置之后的詳細介紹,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-06-06
  • velocity顯示List與Map的方法詳細解析

    velocity顯示List與Map的方法詳細解析

    以下是對velocity顯示List與Map的方法進行了詳細的介紹。需要的朋友可以過來參考下
    2013-08-08

最新評論