今天我們來說說Java中的異常以及異常的解決方式
說到Java中的異常,我們就要先知道什麼是異常。
異常:指的是程序在執行過程中,出現非正常的情況,最終導致jvm(Java虛擬機)的非正常停止。
異常體系
異常機制其實是幫助我們找到程序中的問題,異常的根類是java.lang.Throwable
,其下有兩個子類:java.lang.Error
與java.util.Exception
,平常所說的異常指java.util.Exception
。
Throwable體系:
Error:嚴重錯誤Error,無法通過處理的錯誤,只能事先避免。
Exception:表示異常,異常產生我們可以通過代碼的方式糾正,使程序繼續執行,是必須要處理的。
出現異常不要緊張,把異常的簡單類名,拷貝到ApI中去查。
異常的分類
我們平時說的異常就是指Exception,因爲這類異常一旦出現,我們就要對代碼進行更改。
異常的分類:
編譯時異常:chexked異常。在編譯時,就會檢查,如果沒有處理異常,則編譯失敗(如日期格式化異常)。
運行時異常:runtime異常。在運行時,檢查異常。在編譯時,運行異常不會編譯檢測(不報錯)。如數組越界異常,除0異常。
異常的處理
Java中處理異常的五個關鍵字:try,catch,finally,throw,throws。
拋出異常:throw
在Java中,提供了一個關鍵字throw,用於將程序中不合法的參數,方法返回給調用者,讓調用者傳遞合法的數據進來。
throw用在方法內,用於拋出一個異常對象,將這個異常對象傳遞到調用者處,並結束當前方法的執行。
使用的格式:
throw new 異常類名(參數);
例如: throw new NullPointerException(“要訪問的數組不存在”);
throw new ArrayIndexOutBoundsException(“所輸入的索引越界”);
public class ThrowDemo {
public static void main(String[] args) {
//創建一個數組
double[] d = {5.4,5.5,5.6};
//根據索引找對應的元素
int index = 4;
System.out.println(getElement(d, index));
System.out.println("over");
}
public static double getElement(double[] d,int index) {
//判斷索引是否越界
if(index <0 || index>=d.length-1) {
/*
判斷條件如果滿足,當執行完throw拋出異常對象後,方法已經無法繼續運算。
這時就會結束當前方法的執行,並將異常告知給調用者。這時就需要通過異常來解決。
*/
throw new ArrayIndexOutOfBoundsException("角標又越界了");
}
return d[index];
}
}
執行結果:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 角標又越界了
at laji.ThrowDemo.getElement(ThrowDemo.java:16)
at laji.ThrowDemo.main(ThrowDemo.java:11)
從執行結果中我們可以看到:
我們所寫的“over”並沒有打印出來。所以說,當我們判拋出異常後,mian方法已經結束。
聲明異常:throws
Java中聲明異常的關鍵字throws,用於方法聲明之上,用來表示當前方法不處理異常,而是提醒方法的調用者來處理異常(拋出異常)。
聲明異常格式:修飾符 返回值類型 方法名(參數) throws 異常類名1,異常類名2....{}
聲明異常的代碼演示:
import java.io.FileNotFoundException;
public class ThrowsDemo {
public static void main(String[] args) throws FileNotFoundException {
read("b.txt");
}
//如果定義功能時有問題發生需要報告給調用者,可以通過在方法上使用throws關鍵字進行聲明
public static void read(String path) throws FileNotFoundException {
if(!path.equals("a.txt")) {
throw new FileNotFoundException("文件不存在");
}
}
}
捕獲異常 try...catch
如果異常出現的話,會立刻終止程序,所以我們得處理異常:
1.該方法不處理,而是聲明拋出,由該方法的調用者來處理(throws)
2.在方法中使用try-catch的語句塊來處理異常(手動處理異常)。
try...catch的方式就是捕獲異常。
捕獲異常:Java中對異常有針對性的語句進行捕獲,可以對出現的異常進行制定方式的處理。
語法如下:
try{
編寫可能會出現異常的代碼
}catch(異常類型 e){
處理異常的代碼
//記錄日誌/打印異常信息/繼續拋出異常
}
try:該代碼塊中編寫可能出現異常的代碼
catch:用來進行某種異常的捕獲,實現對捕獲到的異常處理
注:try和catch都不能單獨使用,必須一起。
演示代碼:
import java.io.FileNotFoundException;
public class ThrowsDemo {
public static void main(String[] args) {
try {//當異常產生時,必須有處理方式,要麼捕獲,要麼聲明
read("b.txt");
} catch (FileNotFoundException e) {
//try中拋出的是什麼異常,在括號裏就定義什麼異常類型
System.out.println(e);
}
System.out.println("over");
}
public static void read(String path) throws FileNotFoundException {
if(!path.equals("a.txt")) {
throw new FileNotFoundException("該文件不存在。");
}
}
打印結果:
java.io.FileNotFoundException: 該文件不存在。
over
從上面的代碼我們可以看出,在捕獲異常後,over照樣打印出來,說明捕獲異常不影響之後的代碼。
如何獲取異常信息:
Throwable類中定義了一些查看方法:
public String getMessage()
:獲取異常的描述信息,原因(提示給用戶的時候,就提示錯誤原因。
public void printStackTrace()
:打印異常的跟蹤棧信息並輸出到控制檯。
包含了異常的類型,異常的原因,還包括異常出現的位置,在開發和調試階段,都得使用printStackTrace。
多異常同時捕獲:
try{
編寫可能會出現異常的代碼
}catch(異常類型A e){ 當try中出現A類型異常,就用該catch來捕獲.
處理異常的代碼
//記錄日誌/打印異常信息/繼續拋出異常
}catch(異常類型B e){ 當try中出現B類型異常,就用該catch來捕獲.
處理異常的代碼
//記錄日誌/打印異常信息/繼續拋出異常
}
注意:這種異常處理方式,要求多個catch的異常不能相同,並且若catch的多個異常之間有子父類異常的關係,那麼子類異常需要在父類之上處理
finally代碼塊
finally:在Java中有一些特定的代碼,無論異常是否發生,都需要執行。另外,因爲異常會引發程序跳轉,導致有些語句執行不到。而finally就是解決這個問題的,在finally代碼塊中存放的代碼都一定會被執行的。
什麼時候的代碼必須最終執行?
當我們在try語句塊中打開了一些物理資源(磁盤文件/網絡連接/數據庫連接等),我們都得在使用完之後,最終關閉打開的資源。
finally語法:try...catch....finally:自身需要處理異常,最終還得關閉資源。
注:finally不能單獨使用。
演示代碼如下:
import java.io.FileNotFoundException;
public class ThrowsDemo {
public static void main(String[] args) {
try {
read("b.txt");
} catch (FileNotFoundException e) {
//獲取異常的描述信息,原因 使用方法:.getMessage()
System.out.println(e.getMessage());
}finally {
System.out.println("無論代碼是否異常,這塊都要被執行");
}
System.out.println("over");
}
public static void read(String path) throws FileNotFoundException {
if(!path.equals("a.txt")) {
throw new FileNotFoundException("該文件不存在。");
}
}
}
演示結果:
該文件不存在。
無論代碼是否異常,這塊都要被執行
over
異常注意事項
1.運行時異常被拋出可以不處理。既不捕獲也不聲明拋出。(通過修改代碼解決)
2.當多異常處理時,捕獲處理,前面的類不能是後面的類的父類。
3.在try/catch後可以追加finally代碼塊,其中的代碼一定會被執行,通常用於資源回收。
自定義異常:
異常類如何定義:1.自定義一個編譯期異常:自定義類繼承與java.lang.Exception
2.自定義一個運行時期的異常類:自定義類並繼承於java.lang.RuntimeException。