天天看點

Java異常處理機制詳解(建議收藏儲存)。

前言

異常層次結構圖:

Java異常處理機制詳解(建議收藏儲存)。

一、概述

  1. 異常機制:程式在執行過程中發生了不正常的情況。

代碼示範:

public class ExceptionText {
    public static void main(String[] args) {
        int a=100;
        int b=0;
        System.out.println(a/b);
    }
}      

運作結果:

Java異常處理機制詳解(建議收藏儲存)。

沒有正确輸出,抛出了被 0 除異常

通過以上示例,我們看到 java 給我們提供了這樣一個體系結構,當出現問題的時候,它會告

訴我們,并且把錯誤的詳細資訊也告訴我們了,這就是異常的體系結構,這樣我們的程式更健

壯,我們可以把這個資訊,再進行處理以下告訴使用者。從上面大家還可以看到,java 異常都是

類,在異常類中會攜帶一些資訊給我們,我們可以通過這個類把資訊取出來

  1. java提供異常處理機制,将不正常情況輸出在控制台,供程式員參考,修改代碼,提高代碼的健壯性!!!
  1. 例如常見的:​

    ​ArrayIndexOutOfBoundsException異常​

    ​​、​

    ​ClassCastException異常​

    ​​、​

    ​NullPointerException異常​

  1. 異常在java中以類和對象的形式存在每個類可以建立對象。

  1. Throwable下有兩個分支:Error(不可處理,直接退出JVM)和Exception(可處理的)

    Exception下有兩個分支:Exception的直接子類:編譯時異常(要求程式員在編寫程式階段必須預先對這些異常進行處理,如果不處理編譯器報錯)。RuntimeException:運作時異常。(在編寫程式階段程式員可以預先處理,也可以不處理)

  2. 編譯時異常(受控異常)和運作時異常(非受控異常),都是發生在運作階段。
  3. 編譯時異常和運作時異常的差別?

編譯時異常一般發生的機率比較高。

舉個例子:

你看到外面下雨了,傾盆大雨的。

你出門之前會預料到:如果不打傘,我可能會生病(生病是一種異常)。

而且這個異常發生的機率很高,是以我們出門之前要拿一把傘。

“拿一把傘”就是對“生病異常”發生之前的一種處理方式。

對于一些發生機率較高的異常,需要在運作之前對其進行預處理。

運作時異常一般發生的機率比較低。

舉個例子:

小明走在大街上,可能會被天上的飛機輪子砸到。

被飛機輪子砸到也算一種異常。

但是這種異常發生機率較低。

在出門之前你沒必要提前對這種發生機率較低的異常進行預處理。

如果你預處理這種異常,你将活的很累。

二、異常處理

Java中異常處理有兩種方式:

  • 在方法聲明的位置上,使用throws關鍵字,抛給上一級。誰調用我,我就抛給誰。抛給上一級。
public class ExceptionText {
    public static void main(String[] args) throws Exception{
        int a=100;
        int b=0;
        divide(a,b);
    }

    public static void divide(int a, int b) throws Exception{
        int c = a / b;
        System.out.println(c);
    }
}      
  • 使用try…catch語句進行異常的捕捉。
public class ExceptionText {
    public static void main(String[] args){
        int a=100;
        int b=0;
        try {
            divide(a,b);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void divide(int a, int b) throws Exception{
        int c = a / b;
        System.out.println(c);
    }      

注意:

1.Java中異常發生之後如果一直上抛,最終抛給了main方法,main方法繼續向上抛,抛給了調用者JVM,JVM知道這個異常發生,隻有一個結果。終止java程式的執行。

2.try語句中某一行出現異常該行後續代碼不執行try…catch捕獲後,後續代碼可執行。

try…catch和finally概述

  • 文法格式:
try {

}catch(OneException e) { 

}catch(TwoException e) {

}finally {
 
}      
  • try 中包含了可能産生異常的代碼
  • try 後面是 catch,catch 可以有一個或多個,catch 中是需要捕獲的異常
  • finally 表示:不管是出現異常,還是沒有出現異常,finally 裡的代碼都執行,finally 和 catch

    可以分開使用,但 finally 必須和 try 一塊使用

try {

}finally {

}      
  • ​catch(異常1 | 異常2 |異常3 |......)​

    ​jdk8新特性!!

示例代碼(1):

public class ExceptionText {
    public static void main(String[] args){
        int a=100;
        int b=0;
        try {
            divide(a,b);
            //上一行代碼有異常,直接進入catch裡面!!
            System.out.println("我能執行嗎?");
        } catch (Exception e) {
            System.out.println("被0除了!!");
        }
    }
    public static void divide(int a, int b) throws Exception{
        int c = a / b;
        System.out.println(c);
    }
}      

運作結果:

被0除了!!      

示例代碼(2):

public class ExceptionText {
    public static void main(String[] args){
        int a=100;
        int b=0;
        try {
            divide(a,b);
            //上一行代碼有異常,直接進入catch裡面!!
            System.out.println("我能執行嗎?");
        } catch (Exception e) {
            System.out.println("被0除了!!");
        }finally {
            System.out.println("finally執行了!!");
        }
    }
    public static void divide(int a, int b) throws Exception{
        int c = a / b;
        System.out.println(c);
    }
}      

運作結果:

被0除了!!
finally執行了!!      

throws與try…catch如何選擇?

需要上報異常使用throws,需要捕獲異常時使用try…catch進行捕獲!!

finally重要面試題:

示例代碼(3):

public class FinallyText {
    public static void main(String[] args) {
        System.out.println(n());
    }
    
    public static int n(){
        int i=100;
        try {
            return i;
        }finally {
            i++;
        }
    }
}      

運作結果:你們猜猜?有興趣的鐵子評論區讨論讨論一番哦!!!

Java異常處理機制詳解(建議收藏儲存)。

final、finalize 和 finally差別詳述。

  1. final:是一個關鍵字,表示最終的,不變的,可修飾屬性、方法等!
  2. finalize:是Object類的一個方法,無需程式員調用,JVM垃圾回收器GC調用。
  3. finally:與try一起使用,異常處理機制中,finally語句塊一定執行!!

三、異常中兩個迷人的方法

取得異常描述資訊:getMessage()

示例代碼(4):

public class ExceptionText01 {
    public static void main(String[] args) {
        int a=100;
        int b=0;
        try {
            int c=a/b;
            System.out.println(c);
        }catch (ArithmeticException e){
            //e 是一個引用,它指向了堆中的 ArithmeticException
            //通過 getMessage 可以得到異常的描述資訊
            System.out.println(e.getMessage());
        }
    }
}      

運作結果:

/ by zero      

找不同:找一找下面的結果和上面的結果有什麼不同?

Java異常處理機制詳解(建議收藏儲存)。

取得異常的堆棧資訊(比較适合于程式調試階段):printStackTrace();

示例代碼(5):

public class ExceptionText01 {
    public static void main(String[] args) {
        int a=100;
        int b=0;
        try {
            int c=a/b;
            System.out.println(c);
        }catch (ArithmeticException e){
            //e 是一個引用,它指向了堆中的 ArithmeticException
            //通過 printStackTrace 可以列印棧結構
            e.printStackTrace();
        }
    }
}      

運作結果:

Java異常處理機制詳解(建議收藏儲存)。

比較比較兩個方法在運作結束後,各有什麼不同呢!!!

Java異常處理機制詳解(建議收藏儲存)。

四、手動抛異常

話不多說,直接上代碼!!!

示例代碼(6):

public static void main(String[] args) {
       int ret = method1(1000, 10);
       if (ret == -1) {
           System.out.println("除數為 0");
       }
       if (ret == -2) {
           System.out.println("被除數必須為 1~100 之間的資料");
       }
       if (ret == 1) {
           System.out.println("正确");
       }
   }
    private static int method1(int value1, int value2){
        if (value2 == 0) {
            return -1;
        }
        if (!(value1 >0 && value1<=100)) {
            return -2;
        }
        int value3 = value1/value2;

        System.out.println("value3=" + value3);
        return 1;
    }      

運作結果:

被除數必須為 1~100 之間的資料      

将以上代碼與以下代碼作比較,找不同!!

示例代碼(7):

public static void main(String[] args) {
        try {
            int ret = method1(1000, 10);
            System.out.println(ret);
        }catch(Exception iae) { //可以采用 Exception 攔截所有的異常
            System.out.println(iae.getMessage());
        }
    }
    private static int method1(int value1, int value2){
        if (value2 == 0) {
            //手動抛出異常
            throw new IllegalArgumentException("除數為 0");
        }
        if (!(value1 >0 && value1<=100)) {
            //手動抛出異常
            throw new IllegalArgumentException("被除數必須為 1~100 之間的資料");
        }
        int value3 = value1/value2;
        return value3;
    }      

運作結果:

被除數必須為 1~100 之間的資料      
我們不難看出,使用throw抛出異常的形式來編寫代碼,代碼會變得更加美觀,更加高大上,更加無懈可擊,換句話說,代碼不會太Low!!!(小編建議大家以後可以多多使用)
Java異常處理機制詳解(建議收藏儲存)。

throws 和 throw 的差別?

thorws 是聲明異常,throw是抛出異常

五、神奇的自定義異常

第一步:編寫一個類,繼承Exception或RunTimeException.

第二步:提供兩個構造方法。

示例代碼(8):

public class MyException extends Exception{
    public MyException() {

    }

    public MyException(String s) {
        super(s);
    }
}      

小試牛刀:

編寫程式模拟使用者注冊:

1、程式開始執行時,提示使用者輸入“使用者名”和“密碼”資訊。

2、輸入資訊之後,背景java程式模拟使用者注冊。

3、注冊時使用者名要求長度在[6-14]之間,小于或者大于都表示異常。

代碼示範:

使用者注冊類:

/**
 *使用者登入
 * @username 使用者名
 * @password 密碼
 * 當使用者名為null,使用者名要求長度在[6-14]之間,小于或者大于都表示異常。
 */

class UserService {
    public void register(String username, String password) throws MyException {
        if (null==username || username.length() <= 6 || username.length() >= 14) {
            throw new MyException("輸入有誤,請輸入6~14之間的使用者名");
        }
        System.out.println("恭喜你注冊成功!!");
    }
}      

自定義異常類:

public class MyException extends Exception{
    public MyException() {

    }

    public MyException(String s) {
        super(s);
    }
}      

測試類:

public class ExceptionText {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("請輸入使用者名:");
        String str = input.nextLine();
        System.out.println("請輸入密碼:");
        String passWord = input.next();
        UserService userService = new UserService();
        try {
            userService.register(str, passWord);
        } catch (MyException e) {
            // e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }
}      
請輸入使用者名:
小馬
請輸入密碼:
123456
輸入有誤,請輸入6~14之間的使用者名      
請輸入使用者名:
鵝廠小馬前來報到
請輸入密碼:
123456789
恭喜你注冊成功!!