異常 異常層次 Error:Java 運行時系統的內部錯誤和資源耗盡錯誤。應用程式不應該拋出這種類型的對象。如果出現了這樣的內部錯誤,除了通告給用戶,並儘力使程式安全地終止之外,再也無能為力了。 Exception RuntimeException:由程式錯誤導致的異常 其他異常:程式本身沒有問題, ...
異常
異常層次
- Error:Java 運行時系統的內部錯誤和資源耗盡錯誤。應用程式不應該拋出這種類型的對象。如果出現了這樣的內部錯誤,除了通告給用戶,並儘力使程式安全地終止之外,再也無能為力了。
- Exception
- RuntimeException:由程式錯誤導致的異常
- 其他異常:程式本身沒有問題,但由類似 IO 錯誤導致的異常
Checked 異常 & Runtime 異常
Checked 異常:不是 RuntimeException 類及其子類的異常實例
Runtime 異常:所有 RuntimeException 類及其子類的異常實例
Java 認為 Checked 異常都是可以被處理修複的異常,所以程式必須顯示處理 Checked 異常,如果程式沒有處理 Checked 異常,編譯時會出錯。Checked 異常體現了 Java 的設計理念,沒有完善錯誤處理的代碼根本不會被執行。
對 Checked 異常處理方式:
當前方法明確知道如何處理該異常,應該使用 try-catch 處理該異常
當前方法不知道如何處理該異常,應在定義該方法時聲明拋出該異常
對 Runtime 異常的處理方式:
- Runtime 異常無需顯式聲明拋出,如果程式需要捕獲 Runtime 異常,也可以使用 try-catch 塊
throws 聲明拋出異常
如果當前方法不知道如何處理這種類型的異常,該異常應該由上一級調用者處理,如果上一級調用者也不知道如何處理,再拋出直至交由 JVM 處理。
throws 聲明拋出只能在方法聲明中使用,可以聲明拋出多個異常類。一旦使用 throws 語句聲明拋出該異常,程式就無需使用 try-catch 來捕獲異常了。
示例:下麵程式聲明不處理 IOException 異常,而是將該異常交由 JVM 處理
import java.io.FileInputStream;
import java.io.IOException;
public class ThrowsTest {
public void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("a.txt");
}
}
如果某段代碼中調用了一個帶 throws 聲明的方法,該方法聲明拋出了 Checked 異常,則表明該方法希望它的調用者來處理該異常。那麼調用者在調用該方法時,要麼將其放入 try 塊中並顯示捕獲該異常,要麼放在另一個帶 throws 聲明拋出的方法中。
示例代碼如下:
import java.io.FileInputStream;
import java.io.IOException;
public class ThrowsTest2 {
public static void test() throws IOException {
/* 因為 FileInputStream 的構造器聲明拋出 IOException 異常
所以調用 test() 方法 的代碼要麼處於 try-catch 塊中
要麼處於另一個帶 throws 聲明拋出的方法中
*/
FileInputStream fis = new FileInputStream("a.txt");
}
public static void main(String[] args) throws Exception {
/* 因為 test() 方法聲明拋出 IOException 異常
所以調用該方法的代碼要麼處於 try-catch 塊中
要麼處於另一個帶 throws 聲明拋出的方法中
*/
test();
}
}
主動拋出異常 throw
如果 throw 語句拋出的異常是 Checked 異常,則該 throw 語句要麼處於 try 塊里,顯式捕獲該異常,要麼放在一個帶 throws 聲明拋出的方法中;如果 throw 語句拋出的是 Runtime 異常,則無需放在 try 塊里,也無需放在帶 throws 聲明拋出的方法中,既可以顯式的用 try-catch 來捕獲並處理異常,也可以完全不理會該異常,把該異常交給該方法調用者處理。
import java.io.IOException;
public class ThrowTest3 {
public static void throwChecked(int a) throws Exception {
if (a > 0) {
// 自行拋出 Exception 異常
// 該代碼必須處於 try 塊里,或處於帶 throws 聲明的方法中
throw new Exception("a的值大於0,不符合要求");
}
}
public static void throwRuntime(int a) {
if (a > 0) {
// 自行拋出 RuntimeException 異常
// 既可以捕獲該異常,也可以完全不理會該異常,把異常交給方法調用者處理
throw new RuntimeException("a的值大於0,不符合要求");
}
}
public static void main(String[] args) {
try {
// 調用聲明拋出 Checked 異常的方法,要麼顯式在 try-catch 中捕獲該異常,要麼在 main 方法中再次聲明拋出
throwChecked(3);
} catch (Exception e) {
System.out.print(e.getMessage());
}
// 調用聲明拋出 Runtime 異常的方法既可以顯式捕獲該異常,也可以不理會該異常
throwRuntime(3);
}
}
自定義異常類
public class AuctionException extends Exception {
// 無參構造器
public AuctionException() {}
// 帶一個字元串參數的構造器
public AuctionException(String msg) {
super(msg);
}
}
異常鏈
將原始信息隱藏起來,僅向上提供必要的異常提示信息的處理方式,可以保證底層異常不會擴散到表現層,避免向上暴露太多的細節,符合面向對象的封裝原則。
public calSal() throws SalException {
try {
// 實現結算工資的業務邏輯
...
} catch (SQLException sqle) {
// 將原始異常記錄下來,留給管理員
...
// 下麵異常中的 message 就是給用戶的提示
throw new SalException("訪問資料庫異常“);
} catch (Exception e) {
// 將原始異常記錄下來,留給管理員
...
// 下麵異常中的 message 就是給用戶的提示
throw new SalException("系統出現未知異常“);
}
}
歡迎關註我的公眾號