異常

一、異常的產(chǎn)生

先看下面的這個(gè)demo:

/*
 * 異常的產(chǎn)生
 */

public class ExceptionDemo {
    public static void main(String[] args) {
        System.out.println(0/0);
        System.out.println("hello world");
    }
}

此時(shí)程序就產(chǎn)生 的異常如下:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at exceptions.ExceptionDemo.main(ExceptionDemo.java:11)

分析:

  • JVM檢測(cè)到了問(wèn)題(0是除數(shù)的問(wèn)題),于是程序發(fā)生了異常
  • JVM就把這個(gè)異常進(jìn)行了對(duì)象的封裝new ArithmeticException()
  • 異常對(duì)象被拋給調(diào)用者main中,main方法接收到這個(gè)異常后,由于程序中沒(méi)有對(duì)異常進(jìn)行處理的方法,因此mian方法也不能處理此異常,于是異常又被拋出到JVM中
  • JVM接受到異常后,采取了默認(rèn)的處理措施,停止運(yùn)行程序,于是后面的這個(gè)syso語(yǔ)句沒(méi)有執(zhí)行。

異常也是對(duì)象,上述例子中異常對(duì)象的描述類是ArithmeticException,它是用來(lái)描述數(shù)學(xué)中算數(shù)問(wèn)題的 異常類。比如還有常見(jiàn)的空指針異常描述類NullPointerException。

二、異常的繼承體系

Throwable類是所有異常和錯(cuò)誤的父類

  • Error 錯(cuò)誤

  • Exception 異常

    錯(cuò)誤:程序出現(xiàn)了嚴(yán)重的問(wèn)題,不修改代碼,根本不能運(yùn)行,人得了非典,艾滋,癌

    異常:程序出現(xiàn)了比較輕的問(wèn)題,處理掉之后,繼續(xù)運(yùn)行,人得了闌尾炎,感冒

Exception類是所有異常的父類

  • 非RuntimeException
  • RuntimeException

Throwable中的方法:

  • String toString()重寫(xiě)Object類的方法,異常信息的詳細(xì)描述?
  • String getMessage() 返回異常信息的簡(jiǎn)短描述
  • void printStackTrace() 異常信息輸出到控制臺(tái)

三、異常的兩種處理方式

  1. 直接處理掉異常

    demo:

    try{
      嘗試捕獲異常的代碼
    }catch(異常類 異常變量){
      異常處理代碼
    }
    
  2. 第二種處理方式就是拋出異常

    • throw 手動(dòng)拋出異常,后面寫(xiě)的是new異常的對(duì)象,寫(xiě)在方法中
    • throws 方法聲明拋出異常,后面寫(xiě)的是異常類,寫(xiě)在方法的聲明上

    demo:

    /*
      異常第二種處理方式,拋出異常
      throw throws的用法
    
      ExceptionDemo2.java:21: 錯(cuò)誤: 未報(bào)告的異常錯(cuò)誤Exception; 必須對(duì)其進(jìn)行捕獲或聲明
      以便拋出
          throw new Exception();
      方法中,有異常拋出,但是沒(méi)有處理過(guò),因此編譯失敗
      異常的編譯提示,是Java編譯時(shí)的最后提示
    */
    
    class ExceptionDemo2 
    {
     public static void main(String[] args) throws Exception
     {
         //System.out.println("Hello World!");
         //main中調(diào)用了method方法,方法拋出了異常
         //main有2個(gè)選擇方法,一個(gè)是try...catch
         //另外一個(gè)是,異常我也不處理,交給我的調(diào)用者處理
         method(-5);
     }
     /*
        如果方法的參數(shù)小于0
        程序出現(xiàn)異常,如果參數(shù)大于0 ,程序是正常的
        方法自己,不想處理這個(gè)異常,把異常交給調(diào)用者處理
        在方法聲明上,拋出異常,聲明出來(lái)有異常,交給調(diào)用者
        throws 異常類
     */
     public static void method(int x)throws Exception{
        if(x < 0)
            //程序出現(xiàn)了問(wèn)題
            //手動(dòng)拋出異常
            throw new Exception("程序出現(xiàn)了異常了");
         
         else
             System.out.println("程序正常");
     }
    }
    

四、多層異常的處理

demo

/*
  多層的異常處理方法調(diào)用
*/

class ExceptionDemo3 
{
    public static void main(String[] args) 
    {
        //System.out.println("Hello World!");
        try{
        methodA();
        }catch(Exception e){
        
        }
    }

    public static void methodA()throws Exception{
       methodB();
    }

    public static void methodB()throws Exception{
        methodC();
    }

    public static void methodC()throws Exception{
       throw new Exception();
    }
}

五、finally代碼塊

  • finally可以跟隨try出現(xiàn),也可以跟隨try...catch出現(xiàn)
  • finally代碼塊中的程序,必須要運(yùn)行
  • finally實(shí)際的開(kāi)發(fā)意義,釋放資源

demo

/*
   finally代碼塊
   一定要執(zhí)行
*/

class ExceptionDemo4 
{
    public static void main(String[] args) 
    {
        try{
        method(1);
        }catch(Exception e){
           e.printStackTrace();
        }finally{
            System.out.println("這里的程序必須執(zhí)行");
        }
    }

    public static void method(int x)throws Exception{
       if(x == 1)
           throw new Exception("異常了!!");
       else
           System.out.println("程序正常了");
    }
}

一個(gè)finally的特例:

/*
demo:true or false
*/
class ExceptionDemo5{
  public static void main(String[] args){
    System.out.println(method());
  }
  public static boolean method(){
    
    try{
      return false;
    }catch(Exception e){
      
    }finally{
      return true;
    }
  }
}
//結(jié)果:true


/*
demo2:2 or 10
開(kāi)發(fā)中,不要再try catch中寫(xiě)return
*/
class ExceptionDemo6{
  public static void main(String[] args){
    System.out.println(method());
  }
  public static int method(){
    int i = 1;
    try{
      return ++i;
    }catch(Exception e){
      return 100;
    }finally{
       i=10;
    }
  }
}
//結(jié)果:2

六、編譯時(shí)期的異常

調(diào)用一個(gè)方法,這個(gè)方法拋出一個(gè)異常,此時(shí)調(diào)用者必須處理異常,否則編譯失敗。

Demo

/*
   編譯時(shí)期的異常 
*/
class ExceptionDemo2{
    public static void main(String[] args){
        System.out.printf("hello wordl");
        method();
    }

    public static void method() throws Exception{}
}

結(jié)果如下:

ExceptionDemo2.java:10: 錯(cuò)誤: 未報(bào)告的異常錯(cuò)誤Exception; 必須對(duì)其進(jìn)行捕獲或聲明
以便拋出
        method();
              ^
1 個(gè)錯(cuò)誤

改進(jìn),加上try catch對(duì)異常進(jìn)行處理,錯(cuò)誤提示消失。

/*
   編譯時(shí)期的異常 
*/

class ExceptionDemo2{
    public static void main(String[] args){
        System.out.printf("hello wordl");
        try{
        method();
        }catch(Exception e){}
    }

    public static void method() throws Exception{}
}

七、運(yùn)行時(shí)期的異常

運(yùn)行時(shí)期的異常一旦發(fā)生了,后面的所有程序都不會(huì)接著往下執(zhí)行,所以設(shè)計(jì)運(yùn)行時(shí)期的異常的初衷就很明顯了,這個(gè)異常就是讓開(kāi)發(fā)人員看的,發(fā)生運(yùn)行異常,就必須去修改原代碼,而不是去處理異常。

Demo

/*
  運(yùn)行時(shí)期的異常的特點(diǎn)
*/
class ExceptionDemo3{
    public static void main(String[] args){
        //調(diào)用者不知道方法會(huì)出現(xiàn)異常,所以就不用處理
        //這種時(shí)候,需要修改代碼,而不需要處理
        method();
    }

    public static  void method(){
        //手動(dòng)拋出一個(gè)異常

        throw new RuntimeException();
    }
}

Demo2

/*
  要求:計(jì)算正方形面積,邊長(zhǎng)的平方
  定義方法:求面積,返回結(jié)果
*/
class ExceptionDemo4{
    public static void main(String[] args){
        
        System.out.println(method(-8));
    }

    public static  int method(int num){
        if(num <= 0){
            //邊長(zhǎng)不合法,沒(méi)有必要計(jì)算
            throw new RuntimeException("<= 0");
        }
        return num * num;
    }
}

常見(jiàn)的運(yùn)行時(shí)期的異常:

異常對(duì)象 實(shí)際含義
IndexOutOfBoundsException 越界(字符串,和數(shù)組)
NullPointerException 空指針
ClassCastException 類型轉(zhuǎn)換異常
NoSuchElementException 沒(méi)有元素被取出
IllegalArgumentException 無(wú)效參數(shù)異常

八、自定義異常

Java中異常體系,將很多的情況都做了異常封裝,但是實(shí)際的開(kāi)發(fā)中,不可能把所有的異常都描述完畢,需要自定義的異常,用來(lái)描述自己程序中可能發(fā)生的異常。

自定義異常步驟:

  1. 定義類,后綴名Exception繼承Exception類,或者繼承RuntimeException
  2. 異常信息,自定義的異常類的構(gòu)造方法,把異常信息使用super傳遞到父類

注意:只有異常類,才具備可拋性 throw new 異常體系的類

通過(guò)剛才案例:

  1. 如果一個(gè)方法中,拋出多個(gè)異常,必須要throws聲明多個(gè)異常(運(yùn)行時(shí)起除外)
  2. 調(diào)用者,使用多個(gè)catch進(jìn)行異常的捕獲
  3. 多個(gè)catch中,最大(繼承關(guān)系)的父類,寫(xiě)在最后面,否則編譯失敗

Demo

package exceptions;

/*
 * 自定義異常
 */

//負(fù)數(shù)異常
class FuShuException extends Exception{
     FuShuException(){}

     FuShuException(String info){
        super(info);
    }
}

//0異常
class ZeroException extends Exception{
    ZeroException(){}

    ZeroException(String message){
        super(message);
    }
}


public class ExceptionDemo5 {
    public static void main(String[] args) {
        try{
        getArea(0);
        }catch(FuShuException e){ //多異常,就多catch,范圍越大的往后寫(xiě)
            e.printStackTrace();
        }catch(ZeroException e){
             e.printStackTrace();
        }
    }
    public static int getArea(int num) throws FuShuException,ZeroException{
        if(num < 0){
            throw new FuShuException("邊長(zhǎng)是負(fù)數(shù)");
        }
        else if(num == 0){
             throw new ZeroException("邊長(zhǎng)為0");
        }

        return (int)Math.pow(num,2);
    }
}

九、繼承異常

前提:子類重寫(xiě)父類的方法

  • 父類的方法拋出了異常,子類重寫(xiě)后,異常:父類拋異常,子類可拋可不拋,但是,如果子類拋,不能拋出比父類還大的異常
  • 父類的方法不拋異常,子類重寫(xiě)后,子類不能拋出異常。如果子類重寫(xiě)的方法中,調(diào)用了一個(gè)拋異常的方法,子類別無(wú)選擇,只能try...catch處理異常

demo

package exceptions;

/*
 * 自定義異常
 * 1.父類方法拋異常,子類重寫(xiě)后可拋可不拋,若是拋,則要小于父類(前提是子類重寫(xiě)了父類方法)
 * 2.父類方法不拋異常,子類也不能拋,若是子類調(diào)用的方法拋了異常,子類只能try catch
 */

//A是父類異常類
class AException extends Exception{

}
//B繼承A
class BException extends AException{
    
}
//C和A是兄弟類
class CException extends Exception{
    
}

class Zi extends Fu{
    public void show() throws BException{}
}

class Fu{
    public void show() throws AException{}  
}

public class ExceptionDemo6 {
    public static void main(String[] args) throws AException{
        Fu f = new Zi();
       
          f.show();
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 通俗編程——白話JAVA異常機(jī)制 - 代碼之道,編程之法 - 博客頻道 - CSDN.NEThttp://blog...
    葡萄喃喃囈語(yǔ)閱讀 3,333評(píng)論 0 25
  • Java異常類型 所有異常類型都是Throwable的子類,Throwable把異常分成兩個(gè)不同分支的子類Erro...
    予別她閱讀 1,036評(píng)論 0 2
  • 一、多態(tài) 1. 概述 理解:多態(tài)可以理解為事物存在的多種體(表)現(xiàn)形態(tài)。例如:動(dòng)物中的貓和狗。貓這個(gè)對(duì)象對(duì)應(yīng)的是貓...
    陳凱冰閱讀 379評(píng)論 0 1
  • 今天下午飯都沒(méi)有吃飽就把飯給倒了,因?yàn)橄挛绯燥垥r(shí)間只有半小時(shí),而我們?cè)谒臉巧习?,食堂離我們又遠(yuǎn),走到食堂都5:10...
    掌心日記閱讀 476評(píng)論 0 0
  • 大偉滿足了若希對(duì)男人所有的幻想。知情識(shí)趣,浪漫體貼。明知他永遠(yuǎn)不缺女人,還是愿意默默守候,奢望有天能感動(dòng)他。 這天...
    煙行閱讀 319評(píng)論 0 4

友情鏈接更多精彩內(nèi)容