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 class ExceptionDemo {

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 class ExceptionDemo {

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章