真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java中的異常和異常處理知識(shí)點(diǎn)

這篇文章將為大家詳細(xì)講解有關(guān)Java中的異常和異常處理知識(shí)點(diǎn),小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

作為一家“創(chuàng)意+整合+營(yíng)銷”的成都網(wǎng)站建設(shè)機(jī)構(gòu),我們?cè)跇I(yè)內(nèi)良好的客戶口碑。創(chuàng)新互聯(lián)公司提供從前期的網(wǎng)站品牌分析策劃、網(wǎng)站設(shè)計(jì)、成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)、創(chuàng)意表現(xiàn)、網(wǎng)頁制作、系統(tǒng)開發(fā)以及后續(xù)網(wǎng)站營(yíng)銷運(yùn)營(yíng)等一系列服務(wù),幫助企業(yè)打造創(chuàng)新的互聯(lián)網(wǎng)品牌經(jīng)營(yíng)模式與有效的網(wǎng)絡(luò)營(yíng)銷方法,創(chuàng)造更大的價(jià)值。

一、異常簡(jiǎn)介

什么是異常?

異常就是有異于常態(tài),和正常情況不一樣,有錯(cuò)誤出錯(cuò)。在java中,阻止當(dāng)前方法或作用域的情況,稱之為異常。

java中異常的體系是怎么樣的呢?

1.Java中的所有不正常類都繼承于Throwable類。Throwable主要包括兩個(gè)大類,一個(gè)是Error類,另一個(gè)是Exception類;

Java中的異常和異常處理知識(shí)點(diǎn)

2.其中Error類中包括虛擬機(jī)錯(cuò)誤和線程死鎖,一旦Error出現(xiàn)了,程序就徹底的掛了,被稱為程序終結(jié)者;

Java中的異常和異常處理知識(shí)點(diǎn)

3.Exception類,也就是通常所說的“異常”。主要指編碼、環(huán)境、用戶操作輸入出現(xiàn)問題,Exception主要包括兩大類,非檢查異常(RuntimeException)和檢查異常(其他的一些異常)

Java中的異常和異常處理知識(shí)點(diǎn)

4.RuntimeException異常主要包括以下四種異常(其實(shí)還有很多其他異常,這里不一一列出):空指針異常、數(shù)組下標(biāo)越界異常、類型轉(zhuǎn)換異常、算術(shù)異常。RuntimeException異常會(huì)由java虛擬機(jī)自動(dòng)拋出并自動(dòng)捕獲(就算我們沒寫異常捕獲語句運(yùn)行時(shí)也會(huì)拋出錯(cuò)誤?。。?,此類異常的出現(xiàn)絕大數(shù)情況是代碼本身有問題應(yīng)該從邏輯上去解決并改進(jìn)代碼。

Java中的異常和異常處理知識(shí)點(diǎn)5.檢查異常,引起該異常的原因多種多樣,比如說文件不存在、或者是連接錯(cuò)誤等等。跟它的“兄弟”RuntimeException運(yùn)行異常不同,該異常我們必須手動(dòng)在代碼里添加捕獲語句來處理該異常,這也是我們學(xué)習(xí)java異常語句中主要處理的異常對(duì)象。

Java中的異常和異常處理知識(shí)點(diǎn)

二、try-catch-finally語句

(1)try塊:負(fù)責(zé)捕獲異常,一旦try中發(fā)現(xiàn)異常,程序的控制權(quán)將被移交給catch塊中的異常處理程序。

【try語句塊不可以獨(dú)立存在,必須與 catch 或者 finally 塊同存】

(2)catch塊:如何處理?比如發(fā)出警告:提示、檢查配置、網(wǎng)絡(luò)連接,記錄錯(cuò)誤等。執(zhí)行完catch塊之后程序跳出catch塊,繼續(xù)執(zhí)行后面的代碼。

【編寫catch塊的注意事項(xiàng):多個(gè)catch塊處理的異常類,要按照先catch子類后catch父類的處理方式,因?yàn)闀?huì)【就近處理】異常(由上自下)?!?/p>

(3)finally:最終執(zhí)行的代碼,用于關(guān)閉和釋放資源。

語法格式如下:

try{
//一些會(huì)拋出的異常
}catch(Exception e){
//第一個(gè)catch
//處理該異常的代碼塊
}catch(Exception e){
//第二個(gè)catch,可以有多個(gè)catch
//處理該異常的代碼塊
}finally{
//最終要執(zhí)行的代碼
}

當(dāng)異常出現(xiàn)時(shí),程序?qū)⒔K止執(zhí)行,交由異常處理程序(拋出提醒或記錄日志等),異常代碼塊外代碼正常執(zhí)行。 try會(huì)拋出很多種類型的異常,由多個(gè)catch塊捕獲多鐘錯(cuò)誤。

多重異常處理代碼塊順序問題:先子類再父類(順序不對(duì)編譯器會(huì)提醒錯(cuò)誤),finally語句塊處理最終將要執(zhí)行的代碼。

接下來,我們用實(shí)例來鞏固try-catch語句吧~

先看例子:

package com.hysum.test;

public class TryCatchTest {
    /**
     * divider:除數(shù)
     * result:結(jié)果
     * try-catch捕獲while循環(huán)
     * 每次循環(huán),divider減一,result=result+100/divider
     * 如果:捕獲異常,打印輸出“異常拋出了”,返回-1
     * 否則:返回result
     * @return
     */
    public int test1(){
        int divider=10;
        int result=100;
        try{
            while(divider>-1){
                divider--;
                result=result+100/divider;
            }
            return result;
        }catch(Exception e){
            e.printStackTrace();
            System.out.println("異常拋出了!!");
            return -1;
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TryCatchTest t1=new TryCatchTest();
        System.out.println("test1方法執(zhí)行完畢!result的值為:"+t1.test1());
    }
    
}

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

Java中的異常和異常處理知識(shí)點(diǎn)

結(jié)果分析:結(jié)果中的紅色字拋出的異常信息是由e.printStackTrace()來輸出的,它說明了這里我們拋出的異常類型是算數(shù)異常,后面還跟著原因:by zero(由0造成的算數(shù)異常),下面兩行at表明了造成此異常的代碼具體位置。

在上面例子中再加上一個(gè)test2()方法來測(cè)試finally語句的執(zhí)行狀況:

/**
     * divider:除數(shù)
     * result:結(jié)果
     * try-catch捕獲while循環(huán)
     * 每次循環(huán),divider減一,result=result+100/divider
     * 如果:捕獲異常,打印輸出“異常拋出了”,返回result=999
     * 否則:返回result
     * finally:打印輸出“這是finally,哈哈哈??!”同時(shí)打印輸出result
     * @return
     */
    public int test2(){
        int divider=10;
        int result=100;
        try{
            while(divider>-1){
                divider--;
                result=result+100/divider;
            }
            return result;
        }catch(Exception e){
            e.printStackTrace();
            System.out.println("異常拋出了?。?);
            return result=999;
        }finally{
            System.out.println("這是finally,哈哈哈??!");
            System.out.println("result的值為:"+result);
        }        
    }         
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TryCatchTest t1=new TryCatchTest();
        //System.out.println("test1方法執(zhí)行完畢!result的值為:"+t1.test1());
        t1.test2();
        System.out.println("test2方法執(zhí)行完畢!");
    }

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

Java中的異常和異常處理知識(shí)點(diǎn)

結(jié)果分析:我們可以從結(jié)果看出,finally語句塊是在try塊和catch塊語句執(zhí)行之后最后執(zhí)行的。finally是在return后面的表達(dá)式運(yùn)算后執(zhí)行的(此時(shí)并沒有返回運(yùn)算后的值,而是先把要返回的值保存起來,管finally中的代碼怎么樣,返回的值都不會(huì)改變,仍然是之前保存的值),所以函數(shù)返回值是在finally執(zhí)行前確定的;

這里有個(gè)有趣的問題,如果把上述中的test2方法中的finally語句塊中加上return,編譯器就會(huì)提示警告:finally block does not complete normally

public int test2(){
        int divider=10;
        int result=100;
        try{
            while(divider>-1){
                divider--;
                result=result+100/divider;
            }
            return result;
        }catch(Exception e){
            e.printStackTrace();
            System.out.println("異常拋出了!!");
            return result=999;
        }finally{
            System.out.println("這是finally,哈哈哈??!");
            System.out.println("result的值為:"+result);
            return result;//編譯器警告
        }
        
    }

Java中的異常和異常處理知識(shí)點(diǎn)

分析問題: finally塊中的return語句可能會(huì)覆蓋try塊、catch塊中的return語句;如果finally塊中包含了return語句,即使前面的catch塊重新拋出了異常,則調(diào)用該方法的語句也不會(huì)獲得catch塊重新拋出的異常,而是會(huì)得到finally塊的返回值,并且不會(huì)捕獲異常。

解決問題:面對(duì)上述情況,其實(shí)更合理的做法是,既不在try block內(nèi)部中使用return語句,也不在finally內(nèi)部使用 return語句,而應(yīng)該在 finally 語句之后使用return來表示函數(shù)的結(jié)束和返回。如:

Java中的異常和異常處理知識(shí)點(diǎn)

總結(jié):

1、不管有木有出現(xiàn)異?;蛘遲ry和catch中有返回值return,finally塊中代碼都會(huì)執(zhí)行;

2、finally中最好不要包含return,否則程序會(huì)提前退出,返回會(huì)覆蓋try或catch中保存的返回值。

3、  e.printStackTrace()可以輸出異常信息。

4、  return值為-1為拋出異常的習(xí)慣寫法。

5、  如果方法中try,catch,finally中沒有返回語句,則會(huì)調(diào)用這三個(gè)語句塊之外的return結(jié)果。

6、  finally 在try中的return之后 在返回主調(diào)函數(shù)之前執(zhí)行。

三、throw和throws關(guān)鍵字

java中的異常拋出通常使用throw和throws關(guān)鍵字來實(shí)現(xiàn)。

throw ----將產(chǎn)生的異常拋出,是拋出異常的一個(gè)動(dòng)作。

一般會(huì)用于程序出現(xiàn)某種邏輯時(shí)程序員主動(dòng)拋出某種特定類型的異常。如:

語法:throw (異常對(duì)象),如:

public static void main(String[] args) { 
    String s = "abc"; 
    if(s.equals("abc")) { 
      throw new NumberFormatException(); 
    } else { 
      System.out.println(s); 
    } 
    //function(); 
}

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

Exception in thread "main" java.lang.NumberFormatException
at test.ExceptionTest.main(ExceptionTest.java:67)

throws----聲明將要拋出何種類型的異常(聲明)。

語法格式:

 public void 方法名(參數(shù)列表)
    throws 異常列表{
 //調(diào)用會(huì)拋出異常的方法或者:
 throw new Exception();
 }

當(dāng)某個(gè)方法可能會(huì)拋出某種異常時(shí)用于throws 聲明可能拋出的異常,然后交給上層調(diào)用它的方法程序處理。如:

public static void function() throws NumberFormatException{ 
    String s = "abc"; 
    System.out.println(Double.parseDouble(s)); 
  } 
    
  public static void main(String[] args) { 
    try { 
      function(); 
    } catch (NumberFormatException e) { 
      System.err.println("非數(shù)據(jù)類型不能轉(zhuǎn)換。"); 
      //e.printStackTrace(); 
    } 
}

throw與throws的比較

1、throws出現(xiàn)在方法函數(shù)頭;而throw出現(xiàn)在函數(shù)體。

2、throws表示出現(xiàn)異常的一種可能性,并不一定會(huì)發(fā)生這些異常;throw則是拋出了異常,執(zhí)行throw則一定拋出了某種異常對(duì)象。

3、兩者都是消極處理異常的方式(這里的消極并不是說這種方式不好),只是拋出或者可能拋出異常,但是不會(huì)由函數(shù)去處理異常,真正的處理異常由函數(shù)的上層調(diào)用處理。

來看個(gè)例子:

throws e1,e2,e3只是告訴程序這個(gè)方法可能會(huì)拋出這些異常,方法的調(diào)用者可能要處理這些異常,而這些異常e1,e2,e3可能是該函數(shù)體產(chǎn)生的。

throw則是明確了這個(gè)地方要拋出這個(gè)異常。如:

void doA(int a) throws (Exception1,Exception2,Exception3){
      try{
         ......
 
      }catch(Exception1 e){
       throw e;
      }catch(Exception2 e){
       System.out.println("出錯(cuò)了!");
      }
      if(a!=b)
       throw new Exception3("自定義異常");
}

分析:

1、代碼塊中可能會(huì)產(chǎn)生3個(gè)異常,(Exception1,Exception2,Exception3)。

2、如果產(chǎn)生Exception1異常,則捕獲之后再拋出,由該方法的調(diào)用者去處理。

3、如果產(chǎn)生Exception2異常,則該方法自己處理了(即System.out.println("出錯(cuò)了!");)。所以該方法就不會(huì)再向外拋出Exception2異常了,void doA() throws Exception1,Exception3 里面的Exception2也就不用寫了。因?yàn)橐呀?jīng)用try-catch語句捕獲并處理了。

4、Exception3異常是該方法的某段邏輯出錯(cuò),程序員自己做了處理,在該段邏輯錯(cuò)誤的情況下拋出異常Exception3,則該方法的調(diào)用者也要處理此異常。這里用到了自定義異常,該異常下面會(huì)由解釋。

使用throw和throws關(guān)鍵字需要注意以下幾點(diǎn):

1.throws的異常列表可以是拋出一條異常,也可以是拋出多條異常,每個(gè)類型的異常中間用逗號(hào)隔開

2.方法體中調(diào)用會(huì)拋出異常的方法或者是先拋出一個(gè)異常:用throw new Exception() throw寫在方法體里,表示“拋出異常”這個(gè)動(dòng)作。

3.如果某個(gè)方法調(diào)用了拋出異常的方法,那么必須添加try catch語句去嘗試捕獲這種異常, 或者添加聲明,將異常拋出給更上一層的調(diào)用者進(jìn)行處理

自定義異常

為什么要使用自定義異常,有什么好處?

1、我們?cè)诠ぷ鞯臅r(shí)候,項(xiàng)目是分模塊或者分功能開發(fā)的 ,基本不會(huì)你一個(gè)人開發(fā)一整個(gè)項(xiàng)目,使用自定義異常類就統(tǒng)一了對(duì)外異常展示的方式。

2、有時(shí)候我們遇到某些校驗(yàn)或者問題時(shí),需要直接結(jié)束掉當(dāng)前的請(qǐng)求,這時(shí)便可以通過拋出自定義異常來結(jié)束,如果你項(xiàng)目中使用了SpringMVC比較新的版本的話有控制器增強(qiáng),可以通過@ControllerAdvice注解寫一個(gè)控制器增強(qiáng)類來攔截自定義的異常并響應(yīng)給前端相應(yīng)的信息。

3、自定義異??梢栽谖覀冺?xiàng)目中某些特殊的業(yè)務(wù)邏輯時(shí)拋出異常,比如"中性".equals(sex),性別等于中性時(shí)我們要拋出異常,而Java是不會(huì)有這種異常的。系統(tǒng)中有些錯(cuò)誤是符合Java語法的,但不符合我們項(xiàng)目的業(yè)務(wù)邏輯。

4、使用自定義異常繼承相關(guān)的異常來拋出處理后的異常信息可以隱藏底層的異常,這樣更安全,異常信息也更加的直觀。自定義異??梢話伋鑫覀冏约合胍獟伋龅男畔ⅲ梢酝ㄟ^拋出的信息區(qū)分異常發(fā)生的位置,根據(jù)異常名我們就可以知道哪里有異常,根據(jù)異常提示信息進(jìn)行程序修改。比如空指針異常NullPointException,我們可以拋出信息為“xxx為空”定位異常位置,而不用輸出堆棧信息。

說完了為什么要使用自定義異常,有什么好處,我們?cè)賮砜纯醋远x異常的毛病:

我們不可能期待JVM(Java虛擬機(jī))自動(dòng)拋出一個(gè)自定義異常,也不能夠期待JVM會(huì)自動(dòng)處理一個(gè)自定義異常。發(fā)現(xiàn)異常、拋出異常以及處理異常的工作必須靠編程人員在代碼中利用異常處理機(jī)制自己完成。這樣就相應(yīng)的增加了一些開發(fā)成本和工作量,所以項(xiàng)目沒必要的話,也不一定非得要用上自定義異常,要能夠自己去權(quán)衡。

最后,我們來看看怎么使用自定義異常:

在 Java 中你可以自定義異常。編寫自己的異常類時(shí)需要記住下面的幾點(diǎn)。

所有異常都必須是 Throwable 的子類。

如果希望寫一個(gè)檢查性異常類,則需要繼承 Exception 類。

如果你想寫一個(gè)運(yùn)行時(shí)異常類,那么需要繼承 RuntimeException 類。

可以像下面這樣定義自己的異常類:

class MyException extends Exception{ }

我們來看一個(gè)實(shí)例:

package com.hysum.test;
public class MyException extends Exception {
     /**
     * 錯(cuò)誤編碼
     */
    private String errorCode;   
    public MyException(){}
    
    /**
     * 構(gòu)造一個(gè)基本異常.
     *
     * @param message
     *        信息描述
     */
    public MyException(String message)
    {
        super(message);
    }
    public String getErrorCode() {
        return errorCode;
    }
    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }   
}

使用自定義異常拋出異常信息:

package com.hysum.test;

public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String[] sexs = {"男性","女性","中性"};
                  for(int i = 0; i < sexs.length; i++){
                      if("中性".equals(sexs[i])){
                          try {
                            throw new MyException("不存在中性的人!");
                        } catch (MyException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                     }else{
                         System.out.println(sexs[i]);
                     }
                } 
    }

}

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

Java中的異常和異常處理知識(shí)點(diǎn)

四、java中的異常鏈

異常需要封裝,但是僅僅封裝還是不夠的,還需要傳遞異常。

異常鏈?zhǔn)且环N面向?qū)ο缶幊碳夹g(shù),指將捕獲的異常包裝進(jìn)一個(gè)新的異常中并重新拋出的異常處理方式。原異常被保存為新異常的一個(gè)屬性(比如cause)。這樣做的意義是一個(gè)方法應(yīng)該拋出定義在相同的抽象層次上的異常,但不會(huì)丟棄更低層次的信息。

我可以這樣理解異常鏈:

把捕獲的異常包裝成新的異常,在新異常里添加原始的異常,并將新異常拋出,它們就像是鏈?zhǔn)椒磻?yīng)一樣,一個(gè)導(dǎo)致(cause)另一個(gè)。這樣在最后的頂層拋出的異常信息就包括了最底層的異常信息。

》場(chǎng)景

比如我們的JEE項(xiàng)目一般都又三層:持久層、邏輯層、展現(xiàn)層,持久層負(fù)責(zé)與數(shù)據(jù)庫(kù)交互,邏輯層負(fù)責(zé)業(yè)務(wù)邏輯的實(shí)現(xiàn),展現(xiàn)層負(fù)責(zé)UI數(shù)據(jù)的處理。

有這樣一個(gè)模塊:用戶第一次訪問的時(shí)候,需要持久層從user.xml中讀取數(shù)據(jù),如果該文件不存在則提示用戶創(chuàng)建之。

那問題就來了:如果我們直接把持久層的異常FileNotFoundException拋棄掉,邏輯層根本無從得知發(fā)生任何事情,也就不能為展現(xiàn)層提供一個(gè)友好的處理結(jié)果,最終倒霉的就是展現(xiàn)層:沒有辦法提供異常信息,只能告訴用戶“出錯(cuò)了,我也不知道出了什么錯(cuò)了”—毫無友好性而言。

正確的做法是先封裝,然后傳遞,過程如下:

1、把FileNotFoundException封裝為MyException。

2、拋出到邏輯層,邏輯層根據(jù)異常代碼(或者自定義的異常類型)確定后續(xù)處理邏輯,然后拋出到展現(xiàn)層。

3、展現(xiàn)層自行確定展現(xiàn)什么,如果管理員則可以展現(xiàn)低層級(jí)的異常,如果是普通用戶則展示封裝后的異常。

示例

package com.hysum.test;

public class Main {
    public void test1() throws RuntimeException{
        String[] sexs = {"男性","女性","中性"};
        for(int i = 0; i < sexs.length; i++){
            if("中性".equals(sexs[i])){
                try {
                    throw new MyException("不存在中性的人!");
                } catch (MyException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    RuntimeException rte=new RuntimeException(e);//包裝成RuntimeException異常
                    //rte.initCause(e);
                    throw rte;//拋出包裝后的新的異常
                }
           }else{
               System.out.println(sexs[i]);
           }
      } 
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Main m =new Main();
        
        try{
        m.test1();
        }catch (Exception e){
            e.printStackTrace();
            e.getCause();//獲得原始異常
        }
        
    }

}

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

Java中的異常和異常處理知識(shí)點(diǎn)

結(jié)果分析:我們可以看到控制臺(tái)先是輸出了原始異常,這是由e.getCause()輸出的;然后輸出了e.printStackTrace(),在這里可以看到Caused by:原始異常和e.getCause()輸出的一致。這樣就是形成一個(gè)異常鏈。

initCause()的作用是包裝原始的異常,當(dāng)想要知道底層發(fā)生了什么異常的時(shí)候調(diào)用getCause()就能獲得原始異常。

建議

異常需要封裝和傳遞,我們?cè)谶M(jìn)行系統(tǒng)開發(fā)的時(shí)候,不要“吞噬”異常,也不要“赤裸裸”的拋出異常,封裝后在拋出,或者通過異常鏈傳遞,可以達(dá)到系統(tǒng)更健壯、友好的目的。

五、結(jié)束語

java的異常處理的知識(shí)點(diǎn)雜而且理解起來也有點(diǎn)困難,我在這里給大家總結(jié)了以下幾點(diǎn)使用java異常處理的時(shí)候,良好的編碼習(xí)慣:

1、處理運(yùn)行時(shí)異常時(shí),采用邏輯去合理規(guī)避同時(shí)輔助try-catch處理

2、在多重catch塊后面,可以加一個(gè)catch(Exception)來處理可能會(huì)被遺漏的異常

3、對(duì)于不確定的代碼,也可以加上try-catch,處理潛在的異常

4、盡量去處理異常,切記只是簡(jiǎn)單的調(diào)用printStackTrace()去打印

5、具體如何處理異常,要根據(jù)不同的業(yè)務(wù)需求和異常類型去決定

6、盡量添加finally語句塊去釋放占用的資源

關(guān)于Java中的異常和異常處理知識(shí)點(diǎn)就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。


網(wǎng)頁名稱:Java中的異常和異常處理知識(shí)點(diǎn)
路徑分享:http://weahome.cn/article/ggjocs.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部