異常及其處理(Java)

異常

異常:就是程序出現的不正常的情況。
舉例:
錯誤:這是非常嚴重的問題,一般我們處理不了,一般在這裏指的是硬件問題。
異常:
編譯時期異常:開始就必須要處理的,如果不處理,後面就走不了。
運行時期異常:開始可以不用處理。這種問題一旦發生,就是我們的程序問題,需要我們修改程序。

體系結構:

Throwable:
Error:
Exception:
非RuntimeException:編譯時期異常
RuntimeException:運行時期異常
在這裏插入圖片描述

例如:比如除數不能爲0:java.lang.ArithmeticException: / by zero

public class ExceptionDemo2 {
    public static void main(String[] args) {
        System.out.println("start");
        int a = 10;
        int b = 0;
        System.out.println(a/b);//java.lang.ArithmeticException: / by zero
        System.out.println("end");
    }
}

針對異常,JVM默認的處理方案:

  • 一旦遇到程序出現了問題,就會把問題的類名,錯誤原因,錯誤的位置等信息打印在控制檯,以便我們觀察。並且,會自動從當前出問題的地方停止掉。
  • 這種處理方案雖然可以,但是不夠好。 哪裏不好呢?
    *其實程序出問題,不應該直接停止,因爲我們的程序可能是由多部分組成的,其中一個部分出問題了,不應該影響其他部分的執行。
  • 所以,我們應該讓其他的部分能夠執行下去。

對於上面的問題我們有以下方案兩種方案:
try…catch…finally
throws

try…catch…finally:

try{
可能出現異常的代碼
}catch(異常類名 變量名) {
 針對異常的代碼處理
}finally {
釋放資源的地方
}
簡化一下第一個:
try{
可能出現異常的代碼
}catch(異常類名 變量名) {
針對異常的代碼處理
}
public class ExceptionDemo3 {
    public static void main(String[] args) {
        System.out.println("start");
        int a= 10;
        int b = 0;
        try{
            //可能出現異常的代碼
            System.out.println(a/b);//當除數爲0的時候會拋出ArithmeticException這個異常
                                    //接着程序會拿着這個異常和catch裏面的異常類已經對比                   
        }catch(ArithmeticException e){
            //當程序拋出ArithmeticException這個異常之後給出的具體的處理方法
            System.out.println("你的除數不能爲0");
        }
        System.out.println("end");
    }
}

多個異常的處理:
1.針對每一個出現問題的地方寫一個try…catch語句
2.針對多個異常,採用一個try,多個catch的情況。
try…catch…catch…
注意:有多個catch時候,運行時,只能運行出一個錯誤,而程序不會返回到try
例如下面的程序運行結果:不能運行出除數爲0的結果,遇到try裏面的問題,就自動和catch裏面進行匹配。一旦匹配就執行catch裏面的內容,執行完畢後,接着執行後面的代碼。
注意:如果異常間有子父關係,父必須在最後。(因爲如果異常放在前面,則發生異常的時候都會被父類異常接受,後面會報錯)

package com.edu_01;
public class ExceptionDemo4 {
    public static void main(String[] args) {
        //多個異常處理的第一種解決方案
        //A:給每一個可能出現異常的代碼全部加上try..catch..
/*      try{
            System.out.println(10/0);
        }catch(ArithmeticException e){
            System.out.println("除數不能爲0");
        }
        int[] arr = {1,2,3};
        try{
            System.out.println(arr[3]);//拋出IndexOutOfBoundsException這個異常
        }catch(IndexOutOfBoundsException e){
            System.out.println("數組越界了");
        }*/
        //B:針對多個異常,採用一個try,多個catch的情況。
        //當存在多個catch情況下,如果異常類之間存在子父關係,那麼父類應該放到最後
        int[] arr = {1,2,3};
        try{
            System.out.println(arr[3]);//拋出IndexOutOfBoundsException
            System.out.println(10/0);//拋出ArithmeticException
            arr = null;
            System.out.println(arr[2]);//拋出空指針異常NullpointerException
        }catch(IndexOutOfBoundsException e){//Exception e = new IndexOutOfBoundsException();
            System.out.println("數組越界了");
        }catch(ArithmeticException e){
            System.out.println("除數不能爲0");
        }catch(Exception e){//當前面的異常類都沒有匹配到之後,會自動匹配這個異常
            System.out.println("出現了其他異常");
        }
    }
}

編譯時期異常和運行時期異常的區別:

  • 編譯時期異常:Java程序必須顯示處理,否則程序就會發生錯誤,無法通過編譯
  • FileNotFoundException(文件未找到異常)
  • 運行時期異常:無需顯示處理,也可以和編譯時異常一樣處理
  • ArithmeticException

Throwable中的方法:

  • printStackTrace():打印異常信息,程序從出問題的地方開始就會打印創建一個該異常對應的對象,該對象直接調用打印方法。
public class ExceptionDemo6 {
    public static void main(String[] args) {
        try{
            System.out.println(10/0);//當程序出問題了之後會拋出一個ArithmeticException的對象
            //new ArithmeticException()
        }catch(ArithmeticException e){//ArithmeticException e = new ArithmeticException();
            e.printStackTrace();//打印異常信息
            //java.lang.ArithmeticException: / by zero
            //at com.edu_01.ExceptionDemo6.main(ExceptionDemo6.java:12)
        }
    }
}

throws
表示拋出異常,由該方法的調用者來處理,用在方法聲明後面,跟的是異常類名,可以跟多個異常類名,用“,”號隔開。
throws表示出現異常的一種可能,並不一定會發生這些異常。
try…catch 是直接進行了處理。而throws則是把異常處理的事情交給了調用者。throws用在方法上,聲明方法有異常,交給調用者處理。但是呢,如果是編譯時期異常,調用就必須處理。如果是運行時期異常,調用者可以處理,也可以不處理。

異常處理:
try…catch…finally
finally:一般用於釋放資源。在數據庫操作或者IO流比較常見。
特點:
被finally控制的語句體一定會執行
特殊情況:在執行到finally之前jvm退出了(比如System.exit(0))

public class ExceptionDemo8 {
    public static void main(String[] args) {
        try{
            System.out.println(10/0);
        }catch(ArithmeticException e){
            System.out.println("除數爲0了");
            //在執行finally語句體之前jvm虛擬機退出了,那麼就不會被執行
            System.exit(0);
        }finally{
            //這個代碼塊裏面的代碼一定會被執行的
            System.out.println("我是finally我一定會被執行");
        }
    }
}

final,finally的區別:
final:最終的意思。可以修飾類,方法,變量。
修飾類,類不能被繼承
修飾方法,方法不能被重寫
修飾變量,變量是常量
finally:
異常處理的一部分。被finally控制的代碼一定會執行。
特殊情況:在執行到finally之前,jvm退出了。

注意:
A:子類重寫父類方法時,子類的方法必須拋出相同的異常或父類異常的子類。(父親壞了,兒子不能比父親更壞)
B:如果父類拋出了多個異常,子類重寫父類時,只能拋出相同的異常或者是他的子集,子類不能拋出父類沒有的異常
C:如果被重寫的方法沒有異常拋出,那麼子類的方法絕對不可以拋出異常,如果子類方法內有異常發生,那麼子類只能try,不能throws
上述僅僅針對編譯時期異常,與運行時期異常無關。

throw和throws的區別:
throws:
用在方法聲明後面,跟的是異常類名
可以跟多個異常類名,用逗號隔開
表示拋出異常,由該方法的調用者來處理
throws表示出現異常的一種可能性,並不一定會發生這些異常
throw:
用在方法體內,跟的是異常對象名
只能拋出一個異常對象名
表示拋出異常,由方法體內的語句處理
throw則是拋出了異常,執行throw則一定拋出了某種異常!
注意:如果throw的是編譯時期異常,在方法聲明上必須用throws進行標記,如果throw的是運行時期異常,在方法聲明上可以用throws進行標記,也可以不用。

public class ThrowDemo {
    public static void main(String[] args) {
        method();
        try {
            method2();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
    private static void method2() throws FileNotFoundException{
        try{
            FileInputStream fis = new FileInputStream("D://a.txt");
        }catch(FileNotFoundException e){
            //當遇見這個異常之後,直接拋出(這就是我給出的處理方法)
            //如果【拋出的是編譯時期異常的話,必須在方法聲明上給予聲明
            throw new FileNotFoundException();
        }
    }
    private static void method() throws ArithmeticException{
        int a = 10;
        int b = 2;
        if (b==0) {
            //在這裏拋出的是運行時期異常,拋出這個異常的同時,可以在方法聲明上給予聲明,也可以不聲明
            throw new ArithmeticException();
        }else {
            System.out.println(a/b);
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章