Java異常處理
4、Java異常處理
4.1 Java異常概念
Java異常是Java提供的用于處理程序中錯誤的一種機制。
所謂錯誤是指在程序運行的過程中發生一些異常事件(如:除0溢出,數組下標越界,所要讀取的文件不存在)。
設計良好的程序應該在異常發生時提供處理這些錯位的方法,使得程序不會因為異常的發生而阻斷或產生不可預見的結果。
Java程序的執行過程中如出現異常事件,可以生成一個異常類,該異常類封裝了異常事件的信息并將被提交給Java運行時的系統,這個過程稱為拋出(throw)異常。
當Java運行時系統接收到異常對象時,會尋找能處理這一異常的代碼并把當前異常對象交給其處理,這一過程稱為捕獲(catch)異常。
4.2 異常類型
Throwable
Error Exception(IOException、RuntimeException)
4.3 Java的內置異常
除了java.lang包里定義的異常處理外,在其它java包中還有異常處理。其實,幾乎每個java包里都有相應的異常類來處理相應的異常,但是RuntimeException異常以及其派生的子類是不用處理的,多少從RuntimeException里派生的異常都可以自動調用。注意:我們在處理異常時,可以用catch來捕捉異常,即在運行過程中如果系統發現異常就會將其捕捉下來進行人為的處理;也可以用throw來拋出異常,即在運行過程中某個語句出現了異常如找不到文件等,系統會自動拋出該異常而繼續向下運行程序。這兩種方式各有千秋,通過捕捉異常我們可以更清楚地了解程序運行中存在的異常,以便我們更好的改進;拋出異常可以保證程序的正常運行。但在此提醒大家還是選擇catch異常,這樣如果這個軟件以后有什么bug也好處理。給大家舉個例子,就像我們的ATM機一樣,如果我們在取錢過程中程序運行出現異常,我們當然是希望系統拋出異常,以便我們向銀行反映情況來解決我們遇到的問題,這種方式就是catch異常的好處之一。同時,如果是拋出異常,系統會拋出一大堆專業的術語來,這樣用戶會怎樣想,大家可以想象一下,如果一個人去取錢,突然間屏幕上顯示一大堆我們Java語言拋出異常時的專業術語,這個會怎么想。所以,通過catch異常,我們可以修改異常提示語以便用戶更好地理解。我們再以取錢為例,如果我們選擇程序拋出異常,如果一個人去取錢,突然間程序運行出現異常,但這個異常被拋出了,但現在的問題是拋出后在不知不覺間你的銀行卡余額變少了你會怎么想。所以,建議大家在寫程序時盡量選擇catch 異常。
4.4 Java異常舉例
import java.io.*; public class TestEx { public static void main(String[] args) { try { System.out.println(2 / 0); } catch (ArithmeticException ae) { // 自己定義的異常類對象名,系統將異常對象傳遞給ae里面,ae相當于形參 System.out.println("出錯了"); ae.printStackTrace();// 常用的辦法:把錯誤的堆棧信息打印出來!系統默認也是打印誤的堆棧信息。 } } }
運行結果:
出錯了
java.lang.ArithmeticException: / by zero
at TestEx.main(TestEx.java:7)
4.5 異常的捕獲和處理
在Java語言的異常處理機制里面包括異常捕獲和異常處理兩部分。通過異常處理我們可以人為地處理捕獲到的異常,當然也可以通過相應的方法來處理。
捕獲并處理異常語句格式如下:
try {……; } //可能引發異常的語句
catch(Exception1 e1) {……; }//對異常進行處理
catch(Exception2 e2) {……; }
......
finally {......; } //異常處理結束前的執行程序體
4.6 異常拋出
4.6.1 throw語句
在Java語言中throw語句主動產生一個異常,當程序執行到 throw語句時會拋出一個異常,然后將控制轉到一個相應的catch代碼塊。如果當前方法中沒有catch模塊,那么Java虛擬機將控制轉到調用這個方法的上一個方法中的catch代碼塊中,如果這個方法中還沒有catch模塊,Java虛擬機將繼續在方法的調用棧中向上傳遞控制直到找到能處理這個異常的catch模塊。throw拋出異常語句的一般形式為:
throw new Exception("the program just throw an exception");
4.6.2 throws語句
throws關鍵字是用在方法聲明中,用來列出從方法中發出的、非起源于Error或Runtime Exception中的任何異常(從RuntimeExeeption類型派生的異常通常是可以避免的類型,而從Error類型派生的異常通常與嚴重的系統問題有關)。能夠主動引發異常的方法必須用throws來聲明。一般包含一個throws子句的方法聲明形式為:
type method_name(parameter_list) throws exception_list{}
其中exception_list是該方法可以引發的以逗號分隔的異常列表。
4.6.3 finally語句
finally關鍵字是緊跟在try/catch異常模塊之后的模塊。因為有時我們想執行一段代碼,但在執行該段代碼之前出現了異常,如果出現異常這段代碼就不會被執行,但我們又想執行該段代碼,所以就用到了 finally關鍵字。使用finally關鍵字時,無論其前面的try語句和catch語句怎樣執行以及是否執行,finally語句都必須執行一次。所以,我們把我們想執行的代碼放在finally模塊里就可以保證即使出現異常也能執行。
4.7 自定義異常類
雖然在Java的異常處理機制里面有很強大的異常處理類,但對于某些特殊異常我們還是要自己來處理的,所以我們就要自定義異常類。創建異常類的方法很簡單,只要定義Exception的一個子類就可以實現。由于 Exception繼承自Throwable,因此自定義異常類可以獲得Throwable類中定義的方法,當然也可以在自定義類中重載從 Throwable類中繼承的某些方法。
4.8 異常應用的其他問題
必須先catch較小的異常,再catch大的。
使用自定義的常一般有如下步驟:
a) 通過繼承java.lang.Exception類聲明自己的異常類。
b) 在方法適當的位置生成自定義異常的實例,并用throw語句拋出。
c) 在方法的聲明部分用throws語句聲明該方法可能拋出異常。
異常一致性:重寫方法需要拋出與員方法所拋出異常類型一致異常或不拋出異常。
4.9 異常應用舉例:
import java.io.*; public class TestEx { public static void main(String[] args) { FileInputStream in = null; try { in = new FileInputStream("myfile.txt"); int b; b = in.read(); while (b != -1) { System.out.print((char) b); b = in.read(); } } catch (IOException e) { System.out.println(e.getMessage()); /* * } catch (FileNotFoundException e) { e.printStackTrace(); */ } finally { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } }
運行結果:
myfile.txt (系統找不到指定的文件。)
Exception in thread "main" java.lang.NullPointerException
at TestEx.main(TestEx.java:20)