1 什麼是java異常
異常是指在程序運行時,阻礙程序正常執行的錯誤事件。比如:用戶輸入錯誤數據、硬件故障、網絡阻塞等都會導致出現異常。 只要產生了異常,一個異常對象就會被創建,JRE就會試圖尋找異常處理程序來處理異常。
2 Java異常層級
- Throwable是所有異常的父類,它有兩個直接子對象Error,Exception;
- Error :運行時錯誤;Error對象由JVM生成並拋出,大多數錯誤與開發者無關,所以開發者也不用處理;如:OutOfMemoryError(內存溢出錯誤)、NoClassDefFoundError(類定義錯誤)、LinkageError(鏈接錯誤)等;
Exception分爲檢查型異常和非檢查型異常:
- 檢查型異常:所謂檢查(Checked)是指編譯器必須檢查這類異常,檢查的目的一方面是因爲該類異常的發生難以避免,另一方面就是讓開發者去解決掉這類異常,所以稱爲必須處理(try …catch)的異常。如果不處理這類異常,集成開發環境中的編譯器一般會給出錯誤提示。
例如:一個讀取文件的方法代碼邏輯沒有錯誤,但程序運行時可能會因爲文件找不到而拋出FileNotFoundException,如果不處理這些異常,程序將來肯定會出錯。所以編譯器會提示你要去捕獲並處理這種可能發生的異常,不處理就不能通過編譯.
- 非檢查型異常:所謂非檢查(Unchecked)是指編譯器不會檢查這類異常,不檢查的話則開發者在代碼的編輯編譯階段就不是必須處理,這類異常一般可以避免,因此無需處理(try …catch)。如果不處理這類異常,集成開發環境中的編譯器也不會給出錯誤提示。RuntimeException都屬於Unchecked。
例如:你的程序邏輯本身有問題,比如數組越界、訪問null對象,這種錯誤你自己是可以避免的。編譯器不會強制你檢查這種異常。
3 異常方法
下面的方法都是Throwable的主要方法:
方法 | 說明 |
---|---|
public String getMessage() |
返回異常信息 |
public Throwable getCause() |
返回產生異常的原因 |
public void printStackTrace() |
打印棧軌跡信息到標準錯誤流 |
4 異常處理
4.1 捕獲異常try catch
try
{
// 保護代碼:可能有異常的代碼
}catch(ExceptionName e1)
{
//Catch 塊
}
4.2 多重catch
try{
// 保護代碼:可能有異常的代碼
}catch(ExceptionType1 e1){
// 程序代碼
}catch(ExceptionType2 e2){
// 程序代碼
}catch(ExceptionType3 e2){
// 程序代碼
}
- 如果保護代碼發生異常,異常被拋給第一個 catch 塊;如果拋出異常的類型與 ExceptionType1匹配,它在這裏就會被捕獲,不會繼續向下傳遞;如果不匹配,它會被傳遞給第二個 catch 塊;如此,直到異常被捕獲或者通過所有的 catch 塊。
- 範圍小的異常類(子類)在上面,範圍大的異常類(父類)在下面;
- 儘量不要用try-catch嵌套,結構差;
- 一個catch子句中可以捕獲多個異常,但是並列的異常類型不能具有繼承關係;
catch(IOException | SQLException e)
4.3 throws/throw
-
throws在方法的簽名處聲明此方法可能拋出異常;
-
如果一個方法存在可能有異常的代碼,要進行異常處理,要麼對可能有異常的代碼try-catch,要麼 throws給其調用者處理;
-
可以使用 throw關鍵字拋出一個異常,無論它是新實例化的還是剛捕獲到的。
5 finally
try{
// 保護代碼:可能有異常的代碼
}catch(Exception e){
// 異常處理
}finally{
// 可有可無,finally代碼塊一定會被執行,進行一些清理類型的收尾善後工作
}
6 自定義異常
- 通過繼承Exception類或其子類來實現自定義異常類;
//自定義異常類:分數越界異常
public class OutOfScoreBoundException extends Exception{
public OutOfScoreBoundException(String message) {
super(message);
}
public OutOfScoreBoundException() {
super();
}
}
public class ExceptionDemo {
public static boolean isScoreLegal(int score) throws Exception {//也可以throws OutOfScoreBoundException
if(score>150||score<0){
//拋出自定義異常,下面兩種方式都可以
// throw new Exception("Your score is out of bound");
throw new OutOfScoreBoundException("Your score is out of bound !");
}else {
return true;
}
}
public static void main(String[] args) {//並列catch的Exception類型由小到大
Scanner scanner=new Scanner(System.in);
int score=scanner.nextInt();
try {
if (isScoreLegal(score)){
System.out.println("Your score is legal !");
}
} catch (OutOfScoreBoundException e){
e.printStackTrace();
System.out.println("---->OutOfScoreBoundException");
} catch (Exception e) {
e.printStackTrace();
System.out.println("---->Exception");
}
}
}
160
---->OutOfScoreBoundException
OutOfScoreBoundException: Your score is out of bound !
at ExceptionDemo.isScoreLegal(ExceptionDemo.java:13)
at ExceptionDemo.main(ExceptionDemo.java:23)
7 常見相關面試題
(1)檢查型異常和非檢查型異常的區別?
- 檢查型異常:編譯器必須檢查的異常,此類異常難以避免;開發者必須處理(try-catch),如果不處理,編譯器會有錯誤提示;
- 非檢查型異常:編譯器不用檢查的異常,此類異常可以避免也必須避免;開發者不用處理(try-catch);
(2)throws/throw有什麼區別?
- throws在方法的簽名處聲明此方法可能拋出異常;
- 可以使用 throw關鍵字拋出一個異常,無論它是新實例化的還是剛捕獲到的。
(3) main方法拋出異常時發生了什麼?
- 當main方法拋出異常時,Java運行終止並在控制檯打印異常信息和棧軌跡。
8 參考博客
https://www.runoob.com/java/java-exceptions.html
http://www.importnew.com/7383.html