一、認識異常
- 1.所謂異常指的就是程序在 運行時 出現錯誤時通知調用者的一種機制. 關鍵字 "運行時"
- 2.有些錯誤是這樣的, 例如將 System.out.println 拼寫錯了, 寫成了system.out.println. 此時編譯過程中就會出 錯, 這是 “編譯期” 出錯,而運行時指的是程序已經編譯通過得到 class 文件了, 再由 JVM執行過程中出現的錯誤.
- 3.異常的種類有很多, 不同種類的異常具有不同的含義, 也有不同的處理方式.
二、捕獲和處理異常
基本語法:
try{
有可能出現異常的語句 ;
}[catch (異常類型 異常對象) {
} ... ]
[finally {
異常的出口
}]
注:
- try 代碼塊中放的是可能出現異常的代碼.
- catch 代碼塊中放的是出現異常後的處理行爲.
- finally代碼塊中的代碼用於處理善後工作, 會在最後執行.
- 其中 catch 和 finally 都可以根據情況選擇加或者不加.
1.代碼演示(不處理異常)
public class test {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
System.out.println("frist");
System.out.println(arr[4]);
System.out.println("second");
}
}
//運行結果
frist
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 3
at Exception.test.main(test.java:7)
Process finished with exit code 1
我們發現一旦出現異常, 程序就終止了second 沒有正確輸出.
代碼示例2 使用 try catch 後的程序執行過程
public class test {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
try{System.out.println("frist");
System.out.println(arr[4]);
System.out.println("second");
}catch(ArrayIndexOutOfBoundsException e) {
// 打印出現異常的調用棧
e.printStackTrace();
}
System.out.println("third");
}
//運行結果
frist
java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 3
at Exception.test.main(test.java:7)
third
我們發現, 一旦 try 中出現異常, 那麼 try 代碼塊中的程序就不會繼續執行, 而是交給 catch 中的代碼來執行. catch 執行完畢會繼續往下執行.
代碼示例3 catch 可以有多個
public class test {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
try{System.out.println("frist");
arr = null;
System.out.println(arr[4]);
System.out.println("second");
}catch(ArrayIndexOutOfBoundsException e) {
// 打印出現異常的調用棧
System.out.println("數組下標異常");
e.printStackTrace();
}catch(NullPointerException e){
System.out.println("空指針異常");
e.printStackTrace();
}
System.out.println("third");
}
}
//運行結果
frist
空指針異常
java.lang.NullPointerException
at Exception.test.main(test.java:8)
third
一段代碼可能會拋出多種不同的異常, 不同的異常有不同的處理方式.
因此可以搭配多個 catch 代碼塊.
代碼示例4 finally 表示最後的善後工作, 例如釋放資源
public class test {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
try{System.out.println("frist");
arr = null;
System.out.println(arr[4]);
System.out.println("second");
}catch(ArrayIndexOutOfBoundsException e) {
// 打印出現異常的調用棧
System.out.println("數組下標異常");
e.printStackTrace();
}
finally {
System.out.println("finally ");
}
}
}
//運行結果
frist
finally
Exception in thread "main" java.lang.NullPointerException
at Exception.test.main(test.java:8)
三、異常處理流程
- 程序先執行 try 中的代碼
- 如果 try 中的代碼出現異常, 就會結束 try 中的代碼, 看和 catch 中的異常類型是否匹配.
- 如果找到匹配的異常類型, 就會執行 catch 中的代碼
- 如果沒有找到匹配的異常類型, 就會將異常向上傳遞到上層調用者.
- 無論是否找到匹配的異常類型, finally 中的代碼都會被執行到(在該方法結束之前執行).
- 如果上層調用者也沒有處理的了異常,就繼續向上傳遞.
- 一直到 main 方法也沒有合適的代碼處理異常, 就會交給 JVM 來進行處理, 此時程序就會異常終止.
java異常機制常用到的關鍵字
- 1.try:放置可能會出現異常的代碼
2.catch:參數的類型要匹配 catch可以有多個
3.finally:用來善後,不能有return語句
4.throw:拋出異常 創建一個異常對象
5.throws:異常說明 會拋出的異常有哪些
四、拋出異常
我們可以使用 throws 關鍵字, 把可能拋出的異常顯式的標註在方法定義的位置. 從而提醒調用者要注意捕獲這些異常.
public static int divide(int x, int y) throws ArithmeticException {
if (y == 0) {
throw new ArithmeticException("拋出除 0 異常");
}
return x / y;
}
關於 finally 的注意事項:
finally 中的代碼保證一定會執行到. 這也會帶來一些麻煩.
public static void main(String[] args) {
System.out.println(func());
}
public static int func() {
try {
return 10;
} finally {
return 20;
}
}
// 執行結果
20
注意:
- finally 執行的時機是在方法返回之前(try 或者 catch 中如果有 return 會在這個 return 之前執行finally. 但是如果finally 中也存在 return 語句, 那麼就會執行 finally 中的 return,從而不會執行到 try 中原有的 return.
在以下4種特殊情況下,finally塊不會被執行:
1)在finally語句塊中發生了異常。
2)在前面的代碼中用了System.exit()退出程序。
3)程序所在的線程死亡。
4)關閉CPU。
五、java異常體系
頂層類 Throwable 派生出兩個重要的子類, Error 和 Exception
- Error 指的是 Java 運行時內部錯誤和資源耗盡錯誤. 應用程序不拋出此類異常. 這種內部錯誤一旦出現,除了告知用戶並使程序終止之外, 再無能無力. 這種情況很少出現.
- Exception 是我們程序猿所使用的異常類的父類.
其中 Exception 有一個子類稱爲 RuntimeException , 這裏面又派生出很多我們常見的異常類NullPointerException , IndexOutOfBoundsException 等.
注:
Java語言規範將派生於 Error 類或 RuntimeException 類的所有異常稱爲 非受查異常, 所有的其他異常稱爲 受查異常.
如果一段代碼可能拋出 受查異常, 那麼必須顯式進行處理.