標籤:style blog http color java 使用 os io
一、概述
如果一個人生病了,我們就要對其診斷,然後對症下藥,否則任其病不斷髮展下去或是多種病同時存在,這個人就會變得痛苦,不能正常工作。同樣,java是在網路中啟動並執行,為了保證運行安全,網路能正常的運轉,同樣需要找出程式運行時的錯誤,並能夠及時有效進行處理,則java引出了異常。所謂異常既是不同於正常的,那麼我們也可以稱其為例外。
二、異常架構
異常處理在程式設計時非常重要,是程式設計的一個痛點,在我們學習C++時,同一個異常或者錯誤如果多個地方出現,那麼我們必須每個地方都要做相同處理,感覺相當麻煩。Java語言設計時就考慮這個問題,提出異常處理架構,所有的異常都可以用一個類型來表示,不同類型的異常對應不同的子類異常,定義了異常處理規範。在1.4版本以後增加了異常鏈機制,從而便於跟蹤異常。
Throwable是類庫java.lang包中的一個類,它派生了兩個子類:Error和Exception。
Throwable是可被拋出的,只要任何繼承它的類都可以拋出。
1、Error:系統內部錯誤,是程式無法處理的錯誤。
它表示運行應用程式時較嚴重的問題。大多數錯誤與代碼編寫執行者的操作無關,這些錯誤是不可查的,他們在應用程式的控制和處理能力之外,而表示代碼運行時JVM出現的問題。例如:java虛擬機器運行錯誤、當JVM不再有繼續執行操作所需要的記憶體資源時,將出現OutOfMemoryError。這些異常發生錯誤時,Java虛擬機器一般會選擇終止線程。
2、Exception:程式本身可以處理的異常。
Exception包括:運行時異常錯誤和非運行時異常(編譯異常)。
(1)運行時異常(可查異常):Java編譯器不檢查它,也就是說,當程式中可能出現這類異常,即使沒有用try-catch語句捕獲它,也沒有用throws子句聲明拋出它,也會編譯通過。包括RuntimeException及其子類。這些異常一般是程式邏輯錯誤引起的,程式應該從邏輯角度儘可能避免這類異常的發生。
(2)非運行時異常(不可查異常): Java編譯器會檢查它,也就是說,當程式中可能出現這類異常,要用try-catch語句捕獲它,或用throws子句聲明拋出它,否則編譯不通過。包括除RuntimeException以外的其它類。
補充:可查異常即編譯器要求必須處置的異常:不可查異常即編譯器不要求強制處置的異常,它還包括錯誤(Error)。
Exception同其他類一樣,有自己的屬性和方法,瞭解它有利於我們更好的使用者自訂異常類。
它的兩個建構函式是
Public Exception();
Public Exception(String s);
它的常用方法是
Public StringtoString()//這個方法用來給出詳細的錯誤資訊
Public voidprintStackTrace()//列印出當前異常對象的堆棧使用軌跡,即程式先後執行了那些對象或類的方法,才使得運行過程中產生了這個異常對象。
小結:錯誤和異常的最主要區別:異常可被程式本身處理,錯誤不可以。
三、定義異常
1、 系統定義的運行異常:是系統事先定義好並封裝在java類庫中的。它通常對應著系統運行錯誤,這種錯誤很可能導致作業系統錯誤,甚至整個系統的癱瘓,所以要定義特別類來進行處理。常見的系統定義異常可參見http://soft.chinabyte.com/database/491/12129991.shtml這個網址,這位博主整理的不錯。
2、 使用者自訂的異常:是編程人員根據程式的特殊邏輯在使用者程式裡自己建立使用者自訂的異常類和異常對象。這種使用者自訂異常主要用來處理使用者程式中特定的邏輯運行錯誤。
下面定義的是隊列類的一個出隊方法,這個僅是代碼一部分:
class Queue{int dequeue () //減隊操作,若隊列不空,則從隊列頭部取出一個資料{ int data ;if(!isEmpty()){ data = First.getData();First=First.getNext();return;}else{ return -1}}}
在這個方法裡,如果隊列已經為空白,則此方法給出一個資料“-1”表示出隊的操作失敗,這樣處理的壞處是對壘不能儲存“-1”這個資料,同時還要求其他調用dequeue的方法瞭解這個異常的約定,顯然對程式的調試和運行都不方便,為解決這個問題,可以定義一個程式異常EmptyQueueException,專門處理“從空隊列中出隊”的邏輯錯誤。
class EmptyQueueException extends Exception //使用者自訂的系統類別的子類{Queue queue; public EmptyQueueException(Queue q){ super("隊列已空!");queue = q;}public String toString(){ //重載父類的方法,給出詳細的錯誤資訊 return ("隊列" + queue.toString() + "已經為空白,執行出隊操作引發異常!");}}
四、拋出異常
Java程式在運行時如果引發了一個可以識別的錯誤,就會產生一個與該錯誤對應的異常類對象,這個過程被稱為異常的拋出。
1、 系統自動拋出的異常:系統定義的異常都可以由系統自動拋出。如:以零為除數時出現的算數異常。
2、 語句拋出的異常
使用者自訂的異常不能依靠系統拋出,必須藉助throw語句。並應該拋出這個異常類的新對象如果拋出的是Exception異常類型,則該方法被聲明為拋出所有的異常。多個異常可使用逗號分割。throws語句的文法格式為:
methodname throws Exception1,Exception2,..,ExceptionN { … Thrownew 異常類名; … } ;
以下代碼展示我們怎樣拋出上面的queue()方法可能拋出EmptyQueueExpection異常對象
class Queue{int dequeue () throws EmptyQueneException //減隊操作,若隊列不空,則從隊列頭部取出一個資料{ int data ;if(!isEmpty()){ data = First.getData();First=First.getNext();return;}else{ throw( new EmptyQueueException(this));}}}
拋出異常注意事項:
1、 重寫方法需要拋出與原方法所拋出異常類型一致或者不拋出異常;
2、 必須聲明方法可拋出的任何可查異常(checked exception)。即如果一個方法可能出現受可查異常,要麼用try-catch語句捕獲,要麼用throws子句聲明將它拋出,否則會導致編譯錯誤
3、 在編程中不能在main中拋出異常,要進行處理在main方法中
五、異常處理
當我們拋出異常的時候,要進行異常的處理。異常處理主要包括捕捉異常、程式流程的跳轉和異常處理語句塊的定義。
異常處理的格式:
Try{ //可能會發生異常的程式碼}Catch{ //捕獲並處理try拋出的異常類型,可以有多個catch語句}Finally{ //對程式的狀態做統一的處理}
針對上面的例子,做異常處理,代碼如下:
public class test{public static void main(String args[]){ Queue queue = new Queue(); for ( ing i=1;i<8;i++ ) { queue.enqueue(i); //調用Queue的入隊函數 System.out.println(queue.visitAllNode()); //顯示隊列中的內容 } try { while (!queue.isEmpty()) //調用出隊函數 { System.out.print(queue.dequeue()+"出隊"); System.out.print("隊列中還有" + queue.visitAllNode()); } } catch ( EmptyQueueException eqe) { System.out.println(eqe.toString()); }}}
針對多異常的處理,是定義若干個塊來實現的,每個塊用來接收和處理一種特定的異常對象,並且異常類型小的放前,大的放後,經常出錯的放前,不經常出錯的放後面,因為catch是按先後順序排列的。如果所有的catch塊與不能與當前的異常對象匹配,則說明當前方法不能處理這個異常對象,程式流將返回到調用該方法的上層方法,如果這個上層方法中定義了與所產生的異常對象相匹配的catch塊,流程就轉到這個catch中;否則繼續回溯,如展示情況:
異常處理的原則:
1、避免過大的try塊,不要把不會出現異常的代碼放到try塊裡面,盡量保持一個try塊對應一個或多個異常。
2、細化異常的類型,不要不管什麼類型的異常都寫成Excetpion。
3、catch塊盡量保持一個塊捕獲一類異常,不要忽略捕獲的異常,捕獲到後要麼處理,要麼轉譯,要麼重新拋出新類型的異常。
4、不要用try...catch參與控製程序流程,異常控制的根本目的是處理常式的非正常情況。
六、總結
總之,程式執行時經常會出現除零溢出、數組越界等運行錯誤,影響程式的正常執行。錯誤及異常是不可避免的,一個好的應用程式,在滿足使用者要求的各種功能的同時,還應具備能預見程式執行過程中可能產生的各種異常的能力,並能為異常情況給予恰當處理。Java語言通過物件導向的異常處理機制來解決運行期間的錯誤,可以預防錯誤的程式碼或系統錯誤所造成的不可預期的結果發生。減少編程人員的工作,增加了程式的靈活性,增加程式的可讀性和健壯性。