java異常總結
#01 異常概述
異常分爲兩種
checked異常(JVM檢查時異常)
Runtime異常(運行時異常)
#02 異常處理機制
使用try…catch捕獲異常
try塊業務邏輯代碼出現異常,系統自動捕獲一個異常對象,提交給JVM,即拋出異常
catch塊中包含各種異常對象,執行第一個與try塊中相匹配的對象所對應的代碼塊,即捕獲異常
finally塊中進行資源回收,先finally後return,throw,如果出現System.exit(1)退出虛擬機,finally不會執行
使用throws拋出異常
如果使用throws拋出給JVM(main方法上throws),JVM會打印異常的跟蹤棧信息,並終止程序運行
拋出語法的格式爲:throws ExceptionClass1,ExceptionClass2,ExceptionClass3…
異常拋出的"兩小"原則:自類方法聲明拋出的異常是父類異常的子類或相同,且數量不允許比父類多
異常類的繼承體系
Error錯誤:與虛擬機相關的問題,無法解決
AWTError,IOError,LinkageError,ThreadDeath
Exception:與程序相關的異常,可以捕獲或者拋出,根據異常的繼承關係,先處理子異常
CheckedException(檢查時異常):必須顯示的處理,try…catch或者throws
IOException
SQLException
RuntimeException(運行時異常):無需顯示處理,使用try…catch進行處理
indexOutOfBoundsException
NullPointerException
ClassCastException
多異常捕獲
同一個catch塊捕獲多種異常,異常之間通過 | 隔開,異常變量有隱式的final修飾,不能對異常重新賦值
訪問異常信息
getMessage():返回該異常的詳細描述字符串
printStackTrace():將該異常的跟蹤棧信息輸出到標準錯誤輸出流
printStackTrace(PrintStream s):將該異常的跟蹤棧信息輸出到指定的輸出流
getStackTrace():返回該異常的跟蹤棧信息
public class TestTryCatch {
public static void main(String[] args) {
try{
int[] a = {1,2,3};
int i = a[5];
}catch (Exception e){
e.printStackTrace();
System.out.println();
System.out.println(e);
String message = e.getMessage();
System.out.println(message);
StackTraceElement[] stackTrace = e.getStackTrace();
System.out.println(stackTrace);
}
}
}
輸出結果爲:
java.lang.ArrayIndexOutOfBoundsException: 5
at TestTryCatch.main(TestTryCatch.java:5)
java.lang.ArrayIndexOutOfBoundsException: 5
5
[Ljava.lang.StackTraceElement;@610455d6
異常處理嵌套
在try塊,catch塊或者finally塊中包含完整的異常處理流程的情形被稱爲異常處理的嵌套,不建議超過兩層
特例——Java7種自動關閉資源的try語句
try(聲明或者初始化一個或多個必須在程序結束時關閉的資源類 ){}
這些資源類必須實現AutoCloseable接口或者Closeable接口,資源類在java7中包括IO的各種類,JDBC編程的Connection,Statement等接口
#03 使用throw拋出異常
拋出異常
異常是主觀說法,是否需要拋出異常,需要根據應用的業務需求來決定
使用throw拋出一個異常實例而不是異常類 throw ExceptionInstance;
Checked Exception Instance:需要顯示捕獲該異常並作處理
RuntimeException:可以不理會,講給方法調用者處理
自定義異常
自定義異常應該繼承Exception基類(檢查時異常)或者RuntimeException基類(運行時異常),同時提供兩個構造器,一個是無參構造,一個是以字符串爲參數(該異常對象的描述信息,getMessage()返回的值))的構造
同時使用catch和throw
多個方法同時處理一個異常的情況——在catch塊中結合throw語句
企業級應用對異常的處理:1、應用後臺需要通過日誌來記錄異常發生的詳細信息 2、應用還需要根據異常想應用使用者傳達某種提示
異常鏈
捕獲原始異常,拋出新的業務異常——異常轉義
捕獲一個異常,接着拋出另一個異常,並把原始異常信息保存下來的鏈式處理成爲異常鏈
![image-20190601161709482](/Users/jiang.li/Library/Application Support/typora-user-images/image-20190601161709482.png)
#04 java異常跟蹤棧
異常只要沒有被完全捕獲(包括異常沒有被捕獲,或異常被處理後重新拋出了新的異常),異常從發生異常的方法逐漸向外傳播,首先傳給該方法的調用者,逐次向上,直至main方法,main()沒有處理JVM則會終止程序,並打印棧信息
java.lang.RuntimeException: level 2 exception
at com.msh.demo.exceptionStack.Test.fun2(Test.java:17)
at com.msh.demo.exceptionStack.Test.main(Test.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.io.IOException: level 1 exception
at com.msh.demo.exceptionStack.Test.fun1(Test.java:10)
at com.msh.demo.exceptionStack.Test.fun2(Test.java:15)
... 6 more
第一行信息顯示了異常的類型和詳細信息
跟蹤棧記錄了程序中所有異常發生點,各行顯示被調用方法中執行的停止位置,並標明類、類中的方法名,與故障點對應的文件的行。
跟蹤棧總是最內部的被調用方法逐漸上傳,直到最外部業務操作的起點,通常就是程序的入口main方法或Thread類的run方法
#05 異常處理規則
不要過度使用異常
對於普通的錯誤,應該編寫處理這中錯誤的代碼,增加程序的健壯性,只有對外部的,不能確定和預測的運行時錯誤才使用異常。
異常機制的效率比正常的流程控制效率差