Java核心 -- Exception + Error
概念
- Exception:程式正常執行中,可以 預料 的意外情況,可能並且應該被捕獲,進行相關處理
- Checked Exception:原始碼顯式捕獲處理, 編譯期檢查 ,設計初衷為 從異常情況中恢復
- Unchecked Exception(RuntimeException): 可以編碼避免的邏輯錯誤 ,不會在編譯期強制要求
- Error:在正常情況下,不太可能出現,絕大部分的Error都會導致程式處於 不可恢復 的狀態
ClassNotFoundException
Thrown when an application tries to load in a class through its string name using: The forName method in class Class. The findSystemClass method in class ClassLoader. The loadClass method in class ClassLoader. but no definition for the class with the specified name could be found.
找不到 .class
檔案
NoClassDefFoundError
Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found. The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found.
能找到 .class
檔案,但 ClassLoader
嘗試載入類的定義時卻找不到該類的定義
最佳實踐
反例1
try { // 業務程式碼 Thread.sleep(1000L); } catch (Exception e) { // 忽略 }
- 不要捕獲通用異常
Exception
,應該捕獲 特定異常InterruptedException
- 不要捕獲
Throwable
或Error
,否則很難保證能夠正常處理OutOfMemoryError
- 不要捕獲
- 不要 生吞異常 ,出現故障後 難以診斷
反例2
try { // 業務程式碼 } catch (IOException e) { // Prints this throwable and its backtrace to the standard error stream. e.printStackTrace(); }
- 在複雜的生產環境中,
stderr
不是一個合適的輸出選項,很難判斷輸出到哪裡去了 - 最佳實踐:使用產品日誌,輸出到 日誌系統
Throw early, catch late
Throw early
public static void main(String[] args) throws FileNotFoundException { readFile(null); } private static void readFile(String fileName) throws FileNotFoundException { InputStream in = new FileInputStream(fileName); } // 異常資訊不直觀 Exception in thread "main" java.lang.NullPointerException at java.io.FileInputStream.<init>(FileInputStream.java:130) at java.io.FileInputStream.<init>(FileInputStream.java:93) at me.zhongmingmao.Main.readFile(Main.java:14) at me.zhongmingmao.Main.main(Main.java:9)
public static void main(String[] args) throws FileNotFoundException { readFile(null); } private static void readFile(String fileName) throws FileNotFoundException { Objects.requireNonNull(fileName); InputStream in = new FileInputStream(fileName); } // 使用Throw early,異常資訊比較直觀 Exception in thread "main" java.lang.NullPointerException at java.util.Objects.requireNonNull(Objects.java:203) at me.zhongmingmao.Main.readFile(Main.java:14) at me.zhongmingmao.Main.main(Main.java:10)
Catch late
捕獲異常後,如果實在不知道如何處理,可以保留 原有異常的cause資訊 ,直接 再丟擲 或者 構建新的異常 丟擲
自定義異常
- 是否定義成
Checked Exception
,Checked Exception
的設計初衷是為了 從異常情況中恢復- 我們作為異常的設計者,是有充足的資訊對異常進行分類的,是否滿足
Checked Exception
的設計初衷
- 我們作為異常的設計者,是有充足的資訊對異常進行分類的,是否滿足
- 在保證 診斷資訊 足夠的同時,也需要避免包含 敏感資訊 (例如使用者資訊),可能會導致潛在的 安全問題