人非聖賢,孰能無過,更況且是程序員.因此排錯也是我猿的一項基本技能.java
排錯要先知道有哪些錯,先上圖,而後一項一項分析!程序員
這個類的接口基本決定着java全部異常的行爲,好比經常使用在catch中getMessage(),printStackTrace().其餘詳細以下編程
返回類型安全
方法名稱jvm
方法說明編輯器
Throwableide
fillInStackTrace()工具
在異常堆棧跟蹤中填充。post
Throwable
getCause()
返回此 throwable 的 cause;若是 cause 不存在或未知,則返回 null。
String
getLocalizedMessage()
建立此 throwable 的本地化描述。
String
getMessage()
返回此 throwable 的詳細消息字符串。
StackTraceElement[]
getStackTrace()
提供編程訪問由 printStackTrace() 輸出的堆棧跟蹤信息。
Throwable
initCause(Throwable cause)
將此 throwable 的 cause 初始化爲指定值。
void
printStackTrace()
將此 throwable 及其追蹤輸出至標準錯誤流。
void
printStackTrace(PrintStream s)
將此 throwable 及其追蹤輸出到指定的輸出流。
void
printStackTrace(PrintWriter s)
將此 throwable 及其追蹤輸出到指定的 PrintWriter。
void
setStackTrace(StackTraceElement[] stackTrace)
設置將由 getStackTrace() 返回,並由 printStackTrace() 和相關方法輸出的堆棧跟蹤元素。
String
toString()
返回此 throwable 的簡短描述。
error:系統級別的異常.該錯誤像運行時堆溢出,屬於代碼級不可控範疇.
exception:應用級異常,屬於代碼級可控異常.因此自定義的異常都須要繼承這個接口. 同時exception也包括以下兩類.
家喻戶曉,java中經過try catch來捕捉異常,打到日誌裏爲排錯提供依據.下面對try catch的一些場景進行分析,照例先上一段案例代碼
public class TestTryCatch { public static void main(String[] args) { System.out.println(returnInt()); } public static int returnInt(){ int x; try { x = 1; return x; } catch (NullPointerException e) { x = 2; return x; } finally { x = 3; } } }
jvm的try catch 邏輯是經過Exception table條件來實現的,在from到to的計數行數中爆出的異常從上向下比對type類型,符合的則修改程序計數器中的行數到target指示的行數.
public static int returnInt(); descriptor: ()I flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=4, args_size=0 0: iconst_1 //取1放到棧頂 ---->是try塊中的開始 1: istore_0 //從棧頂將數值放到本地變量(局部變量表第0個變量) 2: iload_0 //保存x到returnValue中 ---->是try塊中的結束 3: istore_1 ---->是finally塊中的開始(沒報錯) 4: iconst_3 //取3放到棧頂 5: istore_0 //從棧頂將數值放到本地變量(局部變量表第0個變量) ---->是finally塊中的結束(沒報錯) 6: iload_1 7: ireturn //返回結果 8: astore_1 //給catch中定義的Exception e賦值 ---->是catch塊中的開始 9: iconst_2 //catch塊中的x=2 10: istore_0 11: iload_0 12: istore_2 // ---->是catch塊中的結束 13: iconst_3 //finaly塊中的x=3 ---->是finally塊中的開始(catch到異常) 14: istore_0 15: iload_2 16: ireturn //返回結果 ---->是finally塊中的結束(catch到異常) 17: astore_3 //若是出現了不屬於java.lang.NullPointerException及其子類的異常纔會走到這裏 18: iconst_3 //finaly塊中的x=3 ---->是finally塊中的開始(沒catch到異常) 19: istore_0 20: aload_3 //將異常放置到棧頂,並拋出 21: athrow // ---->是finally塊中的結束(沒catch到異常) Exception table: from to target type 0 4 8 Class java/lang/NullPointerException 0 4 17 any 8 13 17 any
同時從字節碼能夠看出有以下結果(都假設在x賦值後,return前報錯):
從上能夠得出結論
不要在 finally 塊中使用 return. 通過測試若是finally中加了retrun x;則字節碼中不會出現athrow,而是變爲以下ireturn,因此使用的時候須要注意finally中若是有return那麼異常將不會被拋出.
...... 23: astore_3 24: iconst_3 25: istore_0 26: iload_0 27: ireturn Exception table: from to target type 0 7 11 Class java/lang/NullPointerException 0 7 23 any 11 19 23 any
在阿里泰山版開發手冊中也有說明.
例如這樣一個場景:try中出現了報錯,可是進入到finally執行關閉io的時候也報了錯,那麼結果是方法只會拋出finally中報的錯.addSuppressed能夠用來解決這個問題,能夠同時將try中的錯誤跟finally中的錯誤都拋出.代碼舉例以下:
public static int returnInt() throws IOException{ IOException e = null; int x = 0; try { x = 1; dothing(); return x; }catch (IOException e1){ e = e1; x = 2; return x; }finally { x = 3; try { dothing(); }catch (IOException e2){ if(e != null){ //注意這裏 e.addSuppressed(e2); }else{ e = e2; } } if(e != null){ throw e; } } }
不止各位看官是否以爲上面addSuppressed的書寫方法特別的繁瑣呢,1.7版本的try-catch-resource經過讓資源實現AutoClosable中的close來實現無需手寫,自動調用關閉邏輯的功能;舉例代碼:
public class Connection implements AutoCloseable { public void sendData() { System.out.println("正在發送數據"); } @Override public void close() throws Exception { System.out.println("正在關閉鏈接"); } } --------------------------------------------------- public class TryWithResource { public static void main(String[] args) { try (Connection conn = new Connection()) { conn.sendData(); } catch (Exception e) { e.printStackTrace(); } } }
而後將代碼放在idea裏面查看反編譯代碼
public class TryWithResource { public TryWithResource() { } public static void main(String[] args) { try { Connection conn = new Connection(); Throwable var2 = null; try { conn.sendData(); } catch (Throwable var12) { var2 = var12; throw var12; } finally { if (conn != null) { if (var2 != null) { try { conn.close(); } catch (Throwable var11) { var2.addSuppressed(var11); } } else { conn.close(); } } } } catch (Exception var14) { var14.printStackTrace(); } } }
看吧,原來try-catch-resource就是實質上try-catch-finally加addSuppressed的組合
加入有場景不須要精細判斷,而是須要梭哈異常的狀況下這個註解能夠很方便的幫助你自動生成try-catch,以下代碼
import lombok.SneakyThrows; /** * @author wuzt */ public class TryWithResource { @SneakyThrows public static void main(String[] args) { Connection conn = new Connection(); conn.sendData(); } }
使用idea反編譯後:
public class TryWithResource { public TryWithResource() { } public static void main(String[] args) { try { Connection conn = new Connection(); conn.sendData(); } catch (Throwable var2) { throw var2; } } }
由上發現,其實這個註解的意義就是拋出全部異常
應用的的場景比較符合的像是阿里開發手冊中的以下
求各位看客老爺們點個贊再走啊.