Java 的異常
異常:在Java語言中,將程序執行中發生的不正常情況稱為“異常”。(開發過程中的語法錯誤和邏輯錯誤不是異常)
Java程序在執行過程中所發生的異常事件可分為兩類:
- Error: Java虛擬機無法解決的嚴重問題。如:JVM系統內部錯誤、資源耗盡等嚴重情況。一般不編寫針對性的代碼進行處理。
- Exception: 其它因編程錯誤或偶然的外在因素導致的一般性問題,可以使用針對性的代碼進行處理。例如:
- 空指針訪問
- 試圖讀取不存在的文件
- 網絡連接中斷
對于這些錯誤,一般有兩種解決方法:一是遇到錯誤就終止程序的運行。另一種方法是由程序員在編寫程序時,就考慮到錯誤的檢測、錯誤消息的提示,以及錯誤的處理。
捕獲錯誤最理想的是在編譯期間,但有的錯誤只有在運行時才會發生。比如:除數為0,數組下標越界等
分類:編譯時異常和運行時異常
運行時異常
是指編譯器不要求強制處置的異常。一般是指編程時的邏輯錯誤,是程序員應該積極避免其出現的異常。java.lang.RuntimeException類及它的子類都是運行時異常。
對于這類異常,可以不作處理,因為這類異常很普遍,若全處理可能會對程序的可讀性和運行效率產生影響。
編譯時異常
是指編譯器要求必須處置的異常。即程序在運行時由于外界因素造成的一般性異常。編譯器要求java程序必須捕獲或聲明所有編譯時異常。
對于這類異常,如果程序不處理,可能會帶來意想不到的結果。
異常處理機制
Java采用異常處理機制,將異常處理的程序代碼集中在一起,與正常的程序代碼分開,使得程序簡潔,并易于維護。
Java提供的是異常處理的抓拋模型。
Java程序的執行過程中如出現異常,會生成一個異常類對象,該異常對象將被提交給Java運行時系統,這個過程稱為拋出(throw)異常。
異常對象的生成
- 由虛擬機自動生成:程序運行過程中,虛擬機檢測到程序發生了問題,如果在當前代碼中沒有找到相應的處理程序,就會在后臺自動創建一個對應異常類的實例對象并拋出——自動拋出
- 由開發人員手動創建:Exceptionexception = new ClassCastException();——創建好的異常對象不拋出對程序沒有任何影響,和創建一個普通對象一樣
- 如果一個方法內拋出異常,該異常對象會被拋給調用者方法中處理。如果異常沒有在調用者方法中處理,它繼續被拋給這個調用方法的上層方法。這個過程將一直繼續下去,直到異常被處理。這一過程稱為捕獲(catch)異常。
- 如果一個異常回到main()方法,并且main()也不處理,則程序運行終止。
- 程序員通常只能處理Exception,而對Error無能為力。
捕獲異常
try 捕獲異常的第一步是用try{…}語句塊選定捕獲異常的范圍,將可能出現異常的代碼放在try語句塊中。
catch (Exceptiontype e) 在catch語句塊中是對異常對象進行處理的代碼。每個try語句塊可以伴隨一個或多個catch語句,用于處理可能產生的不同類型的異常對象。
如果明確知道產生的是何種異常,可以用該異常類作為catch的參數;也可以用其父類作為catch的參數。
比如:可以用ArithmeticException類作為參數的地方,就可以用RuntimeException類作為參數,或者用所有異常的父類Exception類作為參數。但不能是與ArithmeticException類無關的異常,如NullPointerException(catch中的語句將不會執行)。
捕獲異常的有關信息:與其它對象一樣,可以訪問一個異常對象的成員變量或調用它的方法。
- getMessage() 獲取異常信息,返回字符串
- printStackTrace() 獲取異常類名和異常信息,以及異常出現在程序中的位置。返回值void。
finally
- 捕獲異常的最后一步是通過finally語句為異常處理提供一個統一的出口,使得在控制流轉到程序的其它部分以前,能夠對程序的狀態作統一的管理。
- 不論在try代碼塊中是否發生了異常事件,catch語句是否執行,catch語句是否有異常,catch語句中是否有return,finally塊中的語句都會被執行。
- finally語句和catch語句是任選的。
public class Test{public static void main(String[] args) {String friends[]={"lisa","bily","kessy"};try {for(int i=0;i<5;i++) {System.out.println(friends[i]);}} catch(ArrayIndexOutOfBoundsException e) {System.out.println("index err");}System.out.println("\nthis is the end");}
}
聲明拋出異常
聲明拋出異常是Java中處理異常的第二種方式
- 如果一個方法(中的語句執行時)可能生成某種異常,但是并不能確定如何處理這種異常,則此方法應顯示地聲明拋出異常,表明該方法將不對這些異常進行處理,而由該方法的調用者負責處理。
- 在方法聲明中用throws語句可以聲明拋出異常的列表,throws后面的異常類型可以是方法中產生的異常類型,也可以是它的父類。
聲明拋出異常舉例:
publicvoid readFile(Stringfile) throwsFileNotFoundException{ …… // 讀文件的操作可能產生FileNotFoundException類型的異常FileInputStreamfis= new FileInputStream(file);..…… }import java.io.*; public class Test6_4{ public static void main(String[] args){Test6_4 t = new Test6_4();try{t.readFile();}catch(IOException e){ } } public void readFile() throws IOException {FileInputStream in=new FileInputStream("myfile.txt");int b; b = in.read();while(b!= -1) {System.out.print((char)b);b = in.read();}in.close(); } }
重寫方法聲明拋出異常的原則
重寫方法不能拋出比被重寫方法范圍更大的異常類型。在多態的情況下,對methodA()方法的調用-異常的捕獲按父類聲明的異常處理。
public class A {public void methodA() throws IOException {……}
}
public class B1 extends A {public void methodA() throws FileNotFoundException {……}
}
public class B2 extends A {public void methodA() throws Exception { //報錯……}
}
人工拋出異常
Java異常類對象除在程序執行過程中出現異常時由系統自動生成并拋出,也可根據需要人工創建并拋出。
首先要生成異常類對象,然后通過throw語句實現拋出操作(提交給Java運行環境)。
IOException e = new IOException();
throw e;
可以拋出的異常必須是Throwable或其子類的實例。下面的語句在編譯時將會產生語法錯誤:
throw new String(“want to throw”);
創建用戶自定義異常類
一般地,用戶自定義異常類都是RuntimeException的子類。
自定義異常類通常需要編寫幾個重載的構造器。
自定義的異常類對象通過throw拋出。
自定義異常最重要的是異常類的名字,當異常出現時,可以根據名字判斷異常類型。
用戶自定義異常類MyException,用于描述數據取值范圍錯誤信息。用戶自己的異常類必須繼承現有的異常類。
class MyException extends Exception {static final long serialVersionUID = 1L; private int idnumber; public MyException(String message, int id) {super(message);this.idnumber = id; } public int getId() {return idnumber; } } //調用 public class Test6_5{public void regist(int num) throws MyException {if (num < 0) throw new MyException(“人數為負值,不合理”, 3);elseSystem.out.println("登記人數" + num );}public void manager() {try {regist(100);} catch (MyException e) {System.out.print("登記失敗,出錯種類"+e.getId()); } System.out.print("本次登記操作結束");}public static void main(String args[]){Test6_5 t = new Test6_5();t.manager();} }