天天看點

Java 異常(一) 異常概述及其架構

Java 異常(一) 異常概述及其架構

一、異常概述

(一)、概述

Java異常是Java提供的一種識别及響應錯誤的一緻性機制。異常指的是程式在執行過程中,出現的非正常的情況,最終會導緻JVM的非正常停止。

Java異常機制可以使程式中異常處理代碼和正常業務代碼分離,保證程式代碼更加優雅,并提高程式健壯性。在有效使用異常的情況下,異常能清晰的回答 what, where, why 這3個問題:異常類型回答了“什麼”被抛出,異常堆棧跟蹤回答了“在哪“抛出,異常資訊回答了“為什麼“會抛出。

(二)、異常體系

異常機制其實是幫助我們找到程式中的問題,異常的根類是java.lang.Throwable,其下有兩個子類:java.lang.Error與java.lang.Exception,平常所說的異常指java.lang.Exception。

Throwable: 有兩個重要的子類:Exception(異常)和 Error(錯誤),二者都是 Java 異常處理的重要子類,各自都包含大量子類。異常和錯誤的差別是:異常能被程式本身可以處理,錯誤是無法處理。

1、Throwable:Throwable是 Java 語言中所有錯誤或異常的超類。Throwable包含兩個子類: Error 和 Exception。它們通常用于訓示發生了異常情況。

Throwable包含了其線程建立時線程執行堆棧的快照,它提供了printStackTrace()等接口用于擷取堆棧跟蹤資料等資訊。

Throwable常用API:

public void printStackTrace() // 列印異常的詳細資訊。包含了異常的類型,異常的原因,還包括異常出現的位置。

public String getMessage() // 擷取發生異常的原因。

public String toString() // 擷取異常的類型和異常描述資訊。

2、Error:嚴重錯誤Error,無法通過處理的錯誤,隻能事先避免。

3、Exception:表示異常,異常産生後程式員可以通過代碼的方式糾正,使程式繼續運作,是必須要處理的。

(三)、異常分類

我們平常說的異常就是指Exception,因為這類異常一旦出現,我們就要對代碼進行更正,修複程式。

異常主要分為兩大類:編譯期異常和運作期異常。

編譯期異常:checked異常。在編譯期,就會檢查,如果沒有處理異常,則編譯失敗(如日期格式化異常)。

特點: Java編譯器會檢查它。此類異常,要麼通過throws進行聲明抛出,要麼通過try-catch進行捕獲處理,否則不能通過編譯。例如,CloneNotSupportedException就屬于被檢查異常。當通過clone()接口去克隆一個對象,而該對象對應的類沒有實作Cloneable接口,就會抛出CloneNotSupportedException異常。被檢查異常通常都是可以恢複的。

運作期異常:runtime異常。在運作時期,檢查異常.在編譯時期,運作異常不會編譯器檢測(不報錯)(如數學異常)。

特點: Java編譯器不會檢查它。也就是說,當程式中可能出現這類異常時,倘若既"沒有通過throws聲明抛出它",也"沒有用try-catch語句捕獲它",還是會編譯通過。例如,除數為零時産生的ArithmeticException異常,數組越界時産生的IndexOutOfBoundsException異常,fail-fail機制産生的ConcurrentModificationException異常等,都屬于運作時異常。

雖然Java編譯器不會檢查運作時異常,但是我們也可以通過throws進行聲明抛出,也可以通過try-catch對它進行捕獲處理。

如果産生運作時異常,則需要通過修改代碼來進行避免。例如,若會發生除數為零的情況,則需要通過代碼避免該情況的發生!

二、異常處理

Java異常處理機制用到的幾個關鍵字:try、catch、finally、throw、throws。

try:用于監聽。将要被監聽的代碼(可能抛出異常的代碼)放在try語句塊之内,當try語句塊内發生異常時,異常就被抛出。

catch:用于捕獲異常。catch用來捕獲try語句塊中發生的異常。

finally:finally語句塊總是會被執行。它主要用于回收在try塊裡打開的物力資源(如資料庫連接配接、網絡連接配接和磁盤檔案)。隻有finally塊,執行完成之後,才會回來執行try或者catch塊中的return或者throw語句,如果finally中使用了return或者throw等終止方法的語句,則就不會跳回執行,直接停止。

throw:用于抛出異常。

throws:用在方法簽名中,用于聲明該方法可能抛出的異常。

三、異常注意點

(一)、finally中的異常會覆寫(消滅)前面try或者catch中的異常

不要在fianlly中使用return。

不要在finally中抛出異常。

減輕finally的任務,不要在finally中做一些其它的事情,finally塊僅僅用來釋放資源是最合适的。

将盡量将所有的return寫在函數的最後面,而不是try ... catch ... finally中。

(二)、多個異常使用捕獲

多個異常分别處理。

多個異常一次捕獲,多次處理。

多個異常一次捕獲一次處理。

一般情況下,一般我們是使用一次捕獲多次處理方式,如下代碼

try{

// 編寫可能會出現異常的代碼           

}catch(異常類型A e){ 當try中出現A類型異常,就用該catch來捕獲.

// 處理異常的代碼
 //記錄日志/列印異常資訊/繼續抛出異常           

}catch(異常類型B e){ 當try中出現B類型異常,就用該catch來捕獲.

// 處理異常的代碼
 //記錄日志/列印異常資訊/繼續抛出異常           

}

注意:這種異常處理方式,要求多個catch中的異常不能相同,并且若catch中的多個異常之間有子父類異常的關系,那麼子類異常要求在上面的catch處理,父類異常在下面的catch處理。

三、執行個體

(一)、try - catch用法

try - catch 必須搭配使用,不能單獨使用。

public class ExceptionDemo {

public static void main(String[] args) {
    try {
        int i = 10 / 0;// 除數不能為0,此行會抛出 ArithmeticException 異常
        System.out.println("i = " + i);// 抛出異常後,此行不會執行
    }catch(ArithmeticException e) { // 捕獲 ArithmeticException 異常
        // 在catch 代碼塊處理異常
        e.printStackTrace(); // 異常最詳細資訊
        System.out.println("e.getMessage() : " + e.getMessage());// 發生異常的原因
        System.out.println("e.toString() : " + e.toString());  // 擷取異常的類型和異常描述資訊
    }
}           

(二)、finally 用法

try - catch - finally搭配使用,或者 try - finally 搭配使用。

public static void main(String[] args) {
    // try-catch-finally搭配使用
    try {
        int[] arr = {1,2,3};
        int i = arr[3];// 數組索引越界,此行會抛出 ArrayIndexOutOfBoundsException 異常
        System.out.println("i = " + i);// 抛出異常後,此行不會執行
    }catch(ArithmeticException e) { // 捕獲 ArithmeticException
        System.out.println(e.getMessage());// 發生異常的原因
        System.exit(0); // 程式強制退出,finally 代碼塊不會執行
    }finally {// 除了程式強制退出,如(System。exit(0)),無論是否發生異常,finally 代碼塊總會執行
        System.out.println("this is finally");
    }
    
    // try-finally搭配使用
    try {
        int[] arr = {1,2,3};
        int i = arr[3];// 數組索引越界,此行會抛出 ArrayIndexOutOfBoundsException 異常
        System.out.println("i = " + i);// 抛出異常後,此行不會執行
    }finally { 
        // 無論是否發生異常,finally 代碼塊總會執行
        System.out.println("this is finally");
    }
}           

注意點:

try-catch-finally 搭配:這種形式捕獲異常時,開發者可以在 catch 代碼塊中處理異常(如列印日志、日志記錄等),異常處理權在開發者。

try-finally 搭配:這種形式捕獲異常時,預設抛出給 JVM 處理,JVM預設處理時調用 e.printStackTrace() 方法列印異常詳細資訊。

finally 代碼塊:除非程式強制退出,否則無論程式是否發生異常,finally 代碼塊總會執行。

finally 中抛出異常會覆寫(消滅)前面 try 或者 catch 中的異常,盡量避免在 finally 代碼塊中抛出異常。

如果 try 中和 finally 中都有 return 語句,程式會先執行 finally 中的 return 語句,然後程式塊運作結束,而不會執行 try 中的 return 語句。是以盡量不在finally中使用 return 語句。

(三)、throw 用法

throw 是用于抛出異常,将這個異常對象傳遞到調用者處,并結束目前方法的執行

public static void main(String[] args) {

  try {

    int i = 10 / 0;

    System.out.println("i = " + i);

  }catch(ArithmeticException e) {

    // 抛出異常,傳遞自定義異常資訊提示

    // 預設抛出給 JVM 處理列印異常詳細資訊

    throw new ArithmeticException("除數不能為0");

  }

(四)、throws 用法

throws運用于方法聲明之上,用于表示目前方法不處理異常,而是提醒該方法的調用者來處理異常(抛出異常)。

public static void main(String[] args) {
    demo();
}
public static void demo() throws ArrayIndexOutOfBoundsException{
    try {
        int[] arr = {1,2,3};
        int i = arr[3];
        System.out.println("i = " + i);
    }catch(ArrayIndexOutOfBoundsException e) { 
       System.out.println(e.toString());
    } 
}           

原文位址

https://www.cnblogs.com/lingq/p/12942895.html