異常的定義
異常:在Java語言中,將程序執(zhí)行中發(fā)生的不正常情況稱為“異?!?。 (開發(fā)過程中的語法錯誤和邏輯錯誤不是異常)
1. 異常的體系結構
Java程序在執(zhí)行過程中所發(fā)生的異常事件可分為兩類:
Error: Java虛擬機無法解決的嚴重問題。如:JVM系統(tǒng)內部錯誤、資源耗盡等嚴重情況。比如: StackOverflowError和OOM。一般不編寫針對性的代碼進行處理。
Exception:其它因編程錯誤或偶然的外在因素導致的一般性問題,可以使用針對性的代碼進行處理。例如:
空指針訪問
試圖讀取不存在的文件
網絡連接中斷
數組角標越界
異常的體系結構 * java.lang.Throwable * |-----java.lang.Error:一般不編寫針對性的代碼進行處理。 * |-----java.lang.Exception:可以進行異常的處理 * |------編譯時異常(checked)不會生成字節(jié)碼文件 * |-----IOException * |-----FileNotFoundException * |-----ClassNotFoundException * |------運行時異常(unchecked,RuntimeException) * |-----NullPointerException//空指針異常* |-----ArrayIndexOutOfBoundsException//數組角標越界* |-----ClassCastException//類型轉化異常* |-----NumberFormatException//編碼格式異常* |-----InputMismatchException//輸入不匹配* |-----ArithmeticException//算術異常
java中異常類的繼承關系

2. 按照異常發(fā)生的時間可以分為兩類
編譯時異常:執(zhí)行javac.exe命名時,可能出現(xiàn)的異常 是指編譯器不要求強制處置的異常。一般是指編程時的邏輯錯誤,是程序員應該積極避免其出現(xiàn)的異常。 java. lang. Runtime Exception類及它的子類都是運行時異常。 對于這類異常,可以不作處理,因為這類異常很普遍,若全處理可能會對程序的可讀性和運行效率產生影響
運行時異常:執(zhí)行java.exe命名時,出現(xiàn)的異常 是指編譯器要求必須處置的異常。即程序在運行時由于外界因素造成的一般性異常。編譯器要求Java程序必須捕獲或聲明所有編譯時異常對于這類異常,如果程序不處理,可能會帶來意想不到的結果。

3.常見的異常類型
//******************以下是運行時異常***************************//ArithmeticException@Testpublicvoidtest6(){inta =10;intb =0;System.out.println(a / b);}//InputMismatchException@Testpublicvoidtest5(){Scanner scanner =newScanner(System.in);intscore = scanner.nextInt();System.out.println(score);scanner.close();}//NumberFormatException@Testpublicvoidtest4(){String str ="123";str ="abc";intnum = Integer.parseInt(str);}//ClassCastException@Testpublicvoidtest3(){Object obj =newDate();String str = (String)obj;}//IndexOutOfBoundsException@Testpublicvoidtest2(){//ArrayIndexOutOfBoundsException// int[] arr = new int[10];// System.out.println(arr[10]);//StringIndexOutOfBoundsExceptionString str ="abc";System.out.println(str.charAt(3));}//NullPointerException@Testpublicvoidtest1(){// int[] arr = null;// System.out.println(arr[3]);String str ="abc";str =null;System.out.println(str.charAt(0));}//******************以下是編譯時異常***************************@Testpublicvoidtest7(){// File file = new File("hello.txt");// FileInputStream fis = new FileInputStream(file);// // int data = fis.read();// while(data != -1){// System.out.print((char)data);// data = fis.read();// }// // fis.close();}
異常的處理
1. java異常處理的抓拋模型
過程一:"拋":程序在正常執(zhí)行的過程中,一旦出現(xiàn)異常,就會在異常代碼處生成一個對應異常類的對象。并將此對象拋出。一旦拋出對象以后,其后的代碼就不再執(zhí)行。
關于異常對象的產生:
① 系統(tǒng)自動生成的異常對象
② 手動的生成一個異常對象,并拋出(throw)
過程二:"抓":可以理解為異常的處理方式:① try-catch-finally ② throws
2.異常處理方式一:try-catch-finally
2.1 使用說明:
try{//可能出現(xiàn)異常的代碼}catch(異常類型1變量名1){//處理異常的方式1}catch(異常類型2變量名2){//處理異常的方式2}catch(異常類型3變量名3){//處理異常的方式3} ....finally{//一定會執(zhí)行的代碼}
說明:
finally是可選的。
使用try將可能出現(xiàn)異常代碼包裝起來,在執(zhí)行過程中,一旦出現(xiàn)異常,就會生成一個對應異常類的對象,根據此對象的類型,去catch中進行匹配
一旦try中的異常對象匹配到某一個catch時,就進入catch中進行異常的處理。一旦處理完成,就跳出當前的try-catch結構(在沒寫finally的情況。繼續(xù)執(zhí)行其后的代碼)
catch中的異常類型如果沒子父類關系,則誰聲明在上,誰聲明在下無所謂。
catch中的異常類型如果滿足子父類關系,則要求子類一定聲明在父類的上面。否則,報錯
常用的異常對象處理的方式: ① String getMessage() ② printStackTrace()
在try結構中聲明的變量,再出了try結構以后,就不能再被調用
try-catch-finally結構可以嵌套
如何看待代碼中的編譯時異常和運行時異常?
使用try-catch-finally處理編譯時異常,是得程序在編譯時就不再報錯,但是運行時仍可能報錯。相當于我們使用try-catch-finally將一個編譯時可能出現(xiàn)的異常,延遲到運行時出現(xiàn)。
開發(fā)中,由于運行時異常比較常見,所以我們通常就不針對運行時異常編寫try-catch-finally了。==針對于編譯時異常,我們說一定要考慮異常的處理==。
2.2. finally的再說明:
finally是可選的
finally中聲明的是一定會被執(zhí)行的代碼。即使catch中又出現(xiàn)異常了,try中return語句,catch中return語句等情況。
像數據庫連接、輸入輸出流、網絡編程Socket等資源,JVM是不能自動的回收的,我們需要自己手動的進行資源的釋放。此時的資源釋放,就需要聲明在finally中。
3. 異常處理方式二:
"throws + 異常類型"==寫在方法的聲明處==。指明此方法執(zhí)行時,可能會拋出的異常類型。 一旦當方法體執(zhí)行時,出現(xiàn)異常,仍會在異常代碼處生成一個異常類的對象,此對象滿足throws后異常類型時,就會被拋出。異常代碼后續(xù)的代碼,就不再執(zhí)行!
4. 對比兩種處理方式
try-catch-finally:真正的將異常給處理掉了。 throws的方式只是將異常拋給了方法的調用者。==并沒真正將異常處理掉==。
5. 開發(fā)中應該如何選擇兩種處理方式?
如果父類中被重寫的方法沒throws方式處理異常,則子類重寫的方法也不能使用throws,意味著如果子類重寫的方法中異常,必須使用try-catch-finally方式處理。
執(zhí)行的方法a中,先后又調用了另外的幾個方法,這幾個方法是遞進關系執(zhí)行的。我們建議這幾個方法使用throws的方式進行處理。而執(zhí)行的方法a可以考慮使用try-catch-finally方式進行處理。
補充: 方法重寫的規(guī)則之一: 子類重寫的方法拋出的異常類型不大于父類被重寫的方法拋出的異常類型
手動拋出異常對象
1.使用說明
在程序執(zhí)行中,除了自動拋出異常對象的情況之外,我們還可以手動的throw一個異常類的對象。
2.經典面試題
throw 和 throws區(qū)別: throw 表示拋出一個異常類的對象,生成異常對象的過程。聲明在方法體內。 throws 屬于異常處理的一種方式,聲明在方法的聲明處。
3.代碼示例
classStudent{privateintid;publicvoidregist(intid)throwsException{if(id >0){this.id = id;}else{//手動拋出異常對象// throw new RuntimeException("您輸入的數據非法!");// throw new Exception("您輸入的數據非法!");thrownewMyException("不能輸入負數");}}@OverridepublicStringtoString(){return"Student [id="+ id +"]";}}
自定義異常類
1.如何自定義異常類
繼承于現(xiàn)的異常結構:RuntimeException 、Exception
提供全局常量:serialVersionUID(對類的唯一標識)
提供重載的構造器
2.代碼示例
publicclassMyExceptionextendsException{staticfinallongserialVersionUID = -7034897193246939L;publicMyException(){}publicMyException(String msg){super(msg);}}
轉自:https://my.oschina.net/RealBruce/blog/3218016