1. 程式人生 > 實用技巧 >【C++primer閱讀記錄】拷貝建構函式和解構函式

【C++primer閱讀記錄】拷貝建構函式和解構函式

異常

異常的定義

異常就是有異於常態,和正常情況不一樣,有錯誤出現。在java中,阻止當前方法或作用域的情況,稱之為異常。

一、 異常機制的概述

  異常機制是指當程式出現錯誤後,程式如何處理。具體來說,異常機制提供了程式退出的安全通道。當出現錯誤後,程式執行的流程發生改變,程式的控制權轉移到異常處理器。

程式錯誤分為三種:1.編譯錯誤;2.執行時錯誤;3.邏輯錯誤。

(1)編譯錯誤是因為程式沒有遵循語法規則,編譯程式能夠自己發現並且提示我們錯誤的原因和位置,這個也是我們大家在剛接觸程式語言最常遇到的問題。

(2)執行時錯誤是因為程式在執行時,執行環境發現了不能執行的操作。

(3)邏輯錯誤是因為程式沒有按照預期的邏輯順序執行。異常也就是指程式執行時發生錯誤,而異常處理就是對這些錯誤進行處理和控制。

二、異常的結構

  Throwable 類是 Java 語言中所有錯誤或異常的超類。只有當物件是此類(或其子類之一)的例項時,才能通過 Java 虛擬機器或者 Java throw 語句丟擲。Throwable 指定程式碼中可用異常傳播機制通過 Java 應用程式傳輸的任何問題的共性。

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

Throwable類中常用api方法有下面幾種:

  1. 返回異常發生時的詳細資訊public string getMessage();

  2. 返回異常發生時的簡要描述public string toString();

  3. 返回異常物件的本地化資訊。使用Throwable的子類覆蓋這個方法,可以聲稱本地化資訊。如果子類沒有覆蓋該方法,則該方法返回的資訊與getMessage()返回的結果相同public string getLocalizedMessage();

  4. 在控制檯上列印Throwable物件封裝的異常資訊public void printStackTrace();

   Error(錯誤):是程式無法處理的錯誤,表示執行應用程式中較嚴重問題。大多數錯誤與程式碼編寫者執行的操作無關,而表示程式碼執行時 JVM(Java 虛擬機器)出現的問題。例如,Java虛擬機器執行錯誤(Virtual MachineError),當 JVM 不再有繼續執行操作所需的記憶體資源時,將出現 OutOfMemoryError。這些異常發生時,Java虛擬機器(JVM)一般會選擇執行緒終止。這些錯誤表示故障發生於虛擬機器自身、或者發生在虛擬機器試圖執行應用時,如Java虛擬機器執行錯誤(Virtual MachineError)、類定義錯誤(NoClassDefFoundError)等。這些錯誤是不可查的,因為它們在應用程式的控制和處理能力之 外,而且絕大多數是程式執行時不允許出現的狀況。對於設計合理的應用程式來說,即使確實發生了錯誤,本質上也不應該試圖去處理它所引起的異常狀況。在 Java中,錯誤通過Error的子類描述。

    Exception(異常):是程式本身可以處理的異常。Exception 類有一個重要的子類 RuntimeException。RuntimeException 類及其子類表示“JVM 常用操作”引發的錯誤。例如,若試圖使用空值物件引用、除數為零或陣列越界,則分別引發執行時異常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。

    Exception(異常)分兩大類:執行時異常和非執行時異常(編譯異常)。程式中應當儘可能去處理這些異常。

    1.執行時異常:都是RuntimeException類及其子類異常,如NullPointerException(空指標異常)、IndexOutOfBoundsException(下標越界異常)等,這些異常是不檢查異常,程式中可以選擇捕獲處理,也可以不處理。這些異常一般是由程式邏輯錯誤引起的,程式應該從邏輯角度儘可能避免這類異常的發生。執行時異常的特點是Java編譯器不會檢查它,也就是說,當程式中可能出現這類異常,即使沒有用try-catch語句捕獲它,也沒有用throws子句宣告丟擲它,也會編譯通過。

    2.非執行時異常 (編譯異常):是RuntimeException以外的異常,型別上都屬於Exception類及其子類。從程式語法角度講是必須進行處理的異常,如果不處理,程式就不能編譯通過。如IOException、SQLException等以及使用者自定義的Exception異常,一般情況下不自定義檢查異常。

    通常,Java的異常(Throwable)分為可查的異常(checked exceptions)不可查的異常(unchecked exceptions)

    1. 可查異常(編譯器要求必須處置的異常):正確的程式在執行中,很容易出現的、情理可容的異常狀況。除了Exception中的RuntimeException及RuntimeException的子類以外,其他的Exception類及其子類(例如:IOException和ClassNotFoundException)都屬於可查異常。這種異常的特點是Java編譯器會檢查它,也就是說,當程式中可能出現這類異常,要麼用try-catch語句捕獲它,要麼用throws子句宣告丟擲它,否則編譯不會通過。  

    2. 不可查異常(編譯器不要求強制處置的異常):包括執行時異常(RuntimeException與其子類)和錯誤(Error)。RuntimeException表示編譯器不會檢查程式是否對RuntimeException作了處理,在程式中不必捕獲RuntimException型別的異常,也不必在方法體宣告丟擲RuntimeException類。RuntimeException發生的時候,表示程式中出現了程式設計錯誤,所以應該找出錯誤修改程式,而不是去捕獲RuntimeException。

異常處理的機制

  在 Java 應用程式中,異常處理機制為:丟擲異常,捕捉異常。

  1. 丟擲異常:當一個方法出現錯誤引發異常時,方法建立異常物件並交付執行時系統,異常物件中包含了異常型別和異常出現時的程式狀態等異常資訊。執行時系統負責尋找處置異常的程式碼並執行。

  2. 捕獲異常:在方法丟擲異常之後,執行時系統將轉為尋找合適的異常處理器(exception handler)。潛在的異常處理器是異常發生時依次存留在呼叫棧中的方法的集合。當異常處理器所能處理的異常型別與方法丟擲的異常型別相符時,即為合適 的異常處理器。執行時系統從發生異常的方法開始,依次回查呼叫棧中的方法,直至找到含有合適異常處理器的方法並執行。當執行時系統遍歷呼叫棧而未找到合適 的異常處理器,則執行時系統終止。同時,意味著Java程式的終止。

  對於錯誤、執行時異常、可查異常,Java技術所要求的異常處理方式有所不同。

  1. 錯誤:對於方法執行中可能出現的Error,當執行方法不欲捕捉時,Java允許該方法不做任何丟擲宣告。因為,大多數Error異常屬於永遠不能被允許發生的狀況,也屬於合理的應用程式不該捕捉的異常。

  2. 執行時異常:由於執行時異常的不可查性,為了更合理、更容易地實現應用程式,Java規定,執行時異常將由Java執行時系統自動丟擲,允許應用程式忽略執行時異常。

  3. 可查異常:對於所有的可查異常,Java規定:一個方法必須捕捉,或者宣告丟擲方法之外。也就是說,當一個方法選擇不捕捉可查異常時,它必須宣告將丟擲異常。

能夠捕捉異常的方法,需要提供相符型別的異常處理器。所捕捉的異常,可能是由於自身語句所引發並丟擲的異常,也可能是由某個呼叫的方法或者Java執行時 系統等丟擲的異常。也就是說,一個方法所能捕捉的異常,一定是Java程式碼在某處所丟擲的異常。簡單地說,異常總是先被丟擲,後被捕捉的。

  異常丟擲:任何Java程式碼都可以丟擲異常,如:自己編寫的程式碼、來自Java開發環境包中程式碼,或者Java執行時系統。無論是誰,都可以通過Java的throw語句丟擲異常。從方法中丟擲的任何異常都必須使用throws。​   異常捕獲:捕捉異常通過try-catch語句或者try-catch-finally語句實現。

  總體來說,Java規定:對於可查異常必須捕捉、或者宣告丟擲。允許忽略不可查的RuntimeException和Error。

Java常見異常

  1. RuntimeException子類:

序號異常名稱異常描述
1 java.lang.ArrayIndexOutOfBoundsException 陣列索引越界異常。當對陣列的索引值為負數或大於等於陣列大小時丟擲。
2 java.lang.ArithmeticException 算術條件異常。譬如:整數除零等。
3 java.lang.SecurityException 安全性異常
4 java.lang.IllegalArgumentException 非法引數異常
5 java.lang.ArrayStoreException 陣列中包含不相容的值丟擲的異常
6 java.lang.NegativeArraySizeException 陣列長度為負異常
7 java.lang.NullPointerException 空指標異常。當應用試圖在要求使用物件的地方使用了null時,丟擲該異常。譬如:呼叫null物件的例項方法、訪問null物件的屬性、計算null物件的長度、使用throw語句丟擲null等等。

  2.IOException

序號異常名稱異常描述
1 IOException 操作輸入流和輸出流時可能出現的異常
2 EOFException 檔案已結束異常
3 FileNotFoundException 檔案未找到異常

  3. 其他

序號異常名稱異常描述
1 ClassCastException 型別轉換異常類
2 ArrayStoreException 陣列中包含不相容的值丟擲的異常
3 SQLException 操作資料庫異常類
4 NoSuchFieldException 欄位未找到異常
5 NoSuchMethodException 方法未找到丟擲的異常
6 NumberFormatException 字串轉換為數字丟擲的異常
7 StringIndexOutOfBoundsException 字串索引超出範圍丟擲的異常
8 IllegalAccessException 不允許訪問某類異常
9 InstantiationException 當應用程式試圖使用Class類中的newInstance()方法建立一個類的例項,而指定的類物件無法被例項化時,丟擲該異常
10 java.lang.ClassNotFoundException 找不到類異常。當應用試圖根據字串形式的類名構造類,而在遍歷CLASSPAH之後找不到對應名稱的class檔案時,丟擲該異常。

五.自定義異常

  使用Java內建的異常類可以描述在程式設計時出現的大部分異常情況。當Java內建的異常都不能明確的說明異常情況的時候,需要建立自己的異常。使用者自定義異常類,只需繼承Exception類即可。

  在程式中使用自定義異常類,大體可分為以下幾個步驟:

  1)建立自定義異常類:一般會選擇繼承Exception和RuntimeException,如果不要求呼叫者一定要處理丟擲的異常,就繼承RuntimeException。

  2)丟擲自定義異常:在方法中通過throw關鍵字丟擲異常物件。

  3)捕獲自定義異常:如果在當前丟擲異常的方法中處理異常,可以使用try-catch語句捕獲並處理;否則在方法的宣告處通過throws關鍵字指明要丟擲給方法呼叫者的異常,繼續進行下一步操作。