Java異常機制

Throwable 是所有 Java 程序中錯誤處理的父類 ,有兩種資類: Error  Exception 

   Error :表示由 JVM 所偵測到的無法預期的錯誤,由於這是屬於 JVM 層次的嚴重錯誤 ,導致 JVM 無法繼續執行,因此,這是不可捕捉到的,無法採取任何恢復的操作,頂多只能顯示錯誤信息。

Exception :表示可恢復的例外,這是可捕捉到的。

Java 提供了兩類主要的異常 :runtime exception  checked exception  checked 異常也就是我們經常遇到的 IO 異常,以及 SQL 異常都是這種異常。 對於這種異常, JAVA 編譯器強制要求我們必需對出現的這些異常進行 catch 。所以,面對這種異常不管我們是否願意,只能自己去寫一大堆 catch 塊去處理可能的異常。

    但是另外一種異常: runtime exception ,也稱運行時異常,我們可以不處理。當出現這樣的異常時,總是由虛擬機 接管。比如:我們從來沒有人去處理過 NullPointerException 異常,它就是運行時異常,並且這種異常還是最常見的異常之一。

    出現運行時異常後,系統會把異常一直往上層拋,一直遇到處理代碼。如果沒有處理塊,到最上層,如果是多線程就由 Thread.run()拋出 ,如果是單線程就被 main() 拋出 。拋出之後,如果是線程,這個線程也就退出了。如果是主程序拋出的異常,那麼這整個程序也就退出了。運行時異常是 Exception 的子類,也有一般異常的特點,是可以被 Catch 塊處理的。只不過往往我們不對他處理罷了。也就是說,你如果不對運行時異常進行處理,那麼出現運行時異常之後,要麼是線程中止,要麼是主程序終止。

    如果不想終止,則必須撲捉所有的運行時異常,決不讓這個處理線程退出。隊列裏面出現異常數據了,正常的處理應該是把異常數據捨棄,然後記錄日誌。不應該由於異常數據而影響下面對正常數據的處理。 在這個場景這樣處理可能是一個比較好的應用,但並不代表在所有的場景你都應該如此。如果在其它場景,遇到了一些錯誤,如果退出程序比較好,這時你就可以不太理會運行時異常 ,或者是通過對異常的處理顯式的控制程序退出。

異常處理的目標之一就是爲了把程序從異常中恢復出來 

 

轉自:http://blog.csdn.net/yakihappy/archive/2009/03/11/3979883.aspx

 

 

異常表示程序運行過程中可能出現的非正常狀態,運行時異常表示虛擬機的通常操作中可能遇到的異常,是一種常見運行錯誤.java編譯器要求方法必須聲明拋出可能發生的非運行時異常,但是並不要求必須聲明拋出未被捕獲的運行時異常.

   下面簡單講解一下有關JAVA異常的知識:

    1. 異常機制

    1.1

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

    1.2

    傳統的處理異常的辦法是,函數返回一個非凡的結果來表示出現異常(通常這個非凡結果是大家約定俗稱的),調用該函數的程序負責檢查並分析函數返回的結果. 這樣做有如下的弊端:例如函數返回-1代表出現異常,但是假如函數確實要返回-1這個正確的值時就會出現混淆;可讀性降低,將程序代碼與處理異常的代碼混 爹在一起;由調用函數的程序來分析錯誤,這就要求客戶程序員對庫函數有很深的瞭解.

    1.3 異常處理的流程

    1.3.1 碰到錯誤,方法立即結束,並不返回一個值;同時,拋出一個異常對象

    1.3.2 調用該方法的程序也不會繼續執行下去,而是搜索一個可以處理該異常的異常處理器,並執行其中的代碼

    2 異常的分類

    2.1 異常的分類

    2.1.1

    異常的繼續結構:基類爲Throwable,Error和Exception繼續Throwable,RuntimeException和 IOException等繼續Exception,具體的RuntimeException繼續RuntimeException.

    2.1.2

    Error和RuntimeException及其子類成爲未檢查異常(unchecked),其它異常成爲已檢查異常(checked).

    2.2 每個類型的異常的特點

    2.2.1 Error體系

    Error類體系描述了Java運行系統中的內部錯誤以及資源耗盡的情形.應用程序不應該拋出這種類型的對象(一般是由虛擬機拋出).假如出現這種錯誤, 除了盡力使程序安全退出外,在其他方面是無能爲力的.所以,在進行程序設計時,應該更關注Exception體系.

    2.2.2 Exception體系

    Exception體系包括RuntimeException體系和其他非RuntimeException的體系

    2.2.2.1 RuntimeException

    RuntimeException體系包括錯誤的類型轉換、數組越界訪問和試圖訪問空指針等等.處理RuntimeException的原則是:假如出現 RuntimeException,那麼一定是程序員的錯誤.例如,可以通過檢查數組下標和數組邊界來避免數組越界訪問異常.

    2.2.2.2 其他(IOException等等)

    這類異常一般是外部錯誤,例如試圖從文件尾後讀取數據等,這並不是程序本身的錯誤,而是在應用環境中出現的外部錯誤.

    2.3 與C++異常分類的不同

    2.3.1

    其實,Java中RuntimeException這個類名起的並不恰當,因爲任何異常都是運行時出現的.(在編譯時出現的錯誤並不是異常,換句話說,異常就是爲了解決程序運行時出現的的錯誤).

    2.3.2

    C++中logic_error與Java中的RuntimeException是等價的,而runtime_error與Java中非RuntimeException類型的異常是等價的.

    3 異常的使用方法

    3.1 聲明方法拋出異常

    3.1.1 語法:throws(略)

    3.1.2 爲什麼要聲明方法拋出異常?

    方法是否拋出異常與方法返回值的類型一樣重要.假設方法拋出異常確沒有聲明該方法將拋出異常,那麼客戶程序員可以調用這個方法而且不用編寫處理異常的代碼.那麼,一旦出現異常,那麼這個異常就沒有合適的異常控制器來解決.

    3.1.3 爲什麼拋出的異常一定是已檢查異常?

    RuntimeException與Error可以在任何代碼中產生,它們不需要由程序員顯示的拋出,一旦出現錯誤,那麼相應的異常會被自動拋出.而已檢 查異常是由程序員拋出的,這分爲兩種情況:客戶程序員調用會拋出異常的庫函數(庫函數的異常由庫程序員拋出);客戶程序員自己使用throw語句拋出異 常.碰到Error,程序員一般是無能爲力的;碰到RuntimeException,那麼一定是程序存在邏輯錯誤,要對程序進行修改(相當於調試的一種 方法);只有已檢查異常纔是程序員所關心的,程序應該且僅應該拋出或處理已檢查異常.

    3.1.4

    注重:覆蓋父類某方法的子類方法不能拋出比父類方法更多的異常,所以,有時設計父類的方法時會聲明拋出異常,但實際的實現方法的代碼卻並不拋出異常,這樣做的目的就是爲了方便子類方法覆蓋父類方法時可以拋出異常.

    3.2 如何拋出異常

    3.2.1 語法:throw(略)

    3.2.2 拋出什麼異常?

    對於一個異常對象,真正有用的信息時異常的對象類型,而異常對象本身毫無意義.比如一個異常對象的類型是ClassCastException,那麼這個類名就是唯一有用的信息.所以,在選擇拋出什麼異常時,最要害的就是選擇異常的類名能夠明確說明異常情況的類.

    3.2.3

    異常對象通常有兩種構造函數:一種是無參數的構造函數;另一種是帶一個字符串的構造函數,這個字符串將作爲這個異常對象除了類型名以外的額外說明.

    3.2.4

    創建自己的異常:當Java內置的異常都不能明確的說明異常情況的時候,需要創建自己的異常.需要注重的是,唯一有用的就是類型名這個信息,所以不要在異常類的設計上花費精力.

    3.3 捕捉異常

    假如一個異常沒有被處理,那麼,對於一個非圖形界面的程序而言,該程序會被中止並輸出異常信息;對於一個圖形界面程序,也會輸出異常的信息,但是程序並不中止,而是返回用戶界面處理循環中.

    3.3.1 語法:try、catch和finally(略)

    控制器模塊必須緊接在try塊後面.若擲出一個異常,異常控制機制會搜尋參數與異常類型相符的第一個控制器隨後它會進入那個catch

    從句,並認爲異常已得到控制.一旦catch 從句結束對控制器的搜索也會停止.

    3.3.1.1 捕捉多個異常(注重語法與捕捉的順序)(略)

    3.3.1.2 finally的用法與異常處理流程(略)

    3.3.2 異常處理做什麼?

    對於Java來說,由於有了垃圾收集,所以異常處理並不需要回收內存.但是依然有一些資源需要程序員來收集,比如文件、網絡連接和圖片等資源.

    3.3.3 應該聲明方法拋出異常還是在方法中捕捉異常?

    原則:捕捉並處理哪些知道如何處理的異常,而傳遞哪些不知道如何處理的異常

    3.3.4 再次拋出異常

    3.3.4.1 爲什麼要再次拋出異常?

    在本級中,只能處理一部分內容,有些處理需要在更高一級的環境中完成,所以應該再次拋出異常.這樣可以使每級的異常處理器處理它能夠處理的異常.

    3.3.4.2 異常處理流程

    對應與同一try塊的catch塊將被忽略,拋出的異常將進入更高的一級.

    4 關於異常的其他問題

    4.1 過度使用異常

    首先,使用異常很方便,所以程序員一般不再願意編寫處理錯誤的代碼,而僅僅是簡簡單單的拋出一個異常.這樣做是不對的,對於完全已知的錯誤,應該編寫處理這種錯誤的代碼,增加程序的魯棒性.另外,異常機制的效率很差.

    4.2 將異常與普通錯誤區分開

    對於普通的完全一致的錯誤,應該編寫處理這種錯誤的代碼,增加程序的魯棒性.只有外部的不能確定和預知的運行時錯誤才需要使用異常.

    4.3 異常對象中包含的信息

    一般情況下,異常對象唯一有用的信息就是類型信息.但使用異常帶字符串的構造函數時,這個字符串還可以作爲額外的信息.調用異常對象的 getMessage()、toString()或者printStackTrace()方法可以分別得到異常對象的額外信息、類名和調用堆棧的信息.並 且後一種包含的信息是前一種的超集.

 

轉自:http://www.zhiweinet.com/jiaocheng/2008-09/1452.htm


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