1. 程式人生 > >執行時異常與一般異常有何異同

執行時異常與一般異常有何異同

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