1、寫在前面
今天文章的内容是:
異常處理
2、内容
2.1、異常方法
Throwable類的主要方法如下所示.
public void printStackTrace():
該方法将此Throwable及其回溯列印到标準錯誤流,列印該對象的堆棧跟蹤。輸出内容中的第一行包含此對象的toString()方法的結果。剩餘行表示先前由方法fillInStackTrace()記錄的資料。
public String toString()
該方法傳回此throwable的簡短描述,即printStackTrace()方法調用後輸出内容中的第一行。
public Throwable getCause()
該方法傳回一個Throwable對象代表異常原因。如果原因不存在或未知,則傳回此throwable或null的原因。
public String getMessage()
該方法傳回關于發生的異常的詳細資訊字元串(也可能是null),該字元串在Throwable類的構造函數中初始化了。
public StackTraceElement [] getStackTrace()
該方法傳回堆棧跟蹤元素的數組,每個元素代表一個堆棧幀。下标為0的元素代表棧頂,最後一個元素代表方法調用堆棧的棧底。
public Throwable fillInStackTrace()
該方法在此Throwable對象中記錄有關目前線程的堆棧幀的目前狀态的資訊。即用目前的調用棧層次填充Throwable 對象棧層次,添加到棧層次任何先前資訊中。
2.2、throws
異常的處理方式之一就是使用throws關鍵字來抛出異常。
文法如下:
方法 throws 異常1, 異常2, ... {
}
有時抛出的異常比較多,我們會這樣做:
方法 throws Exception {
}
綜上所述,throws關鍵字用在方法上,可以将方法内部出現的異常抛給方法調用處。但注意,這種異常處理方式其實并不好,發生異常的方法自己不處理,最終抛出去的異常會由虛拟機接受,最終程式會終止退出。
throw跟throws的差別:
public void test() throws Exception {
throw new Exception();
}
在上面這段代碼中可以看出:
throws表示方法聲明可能抛出一個異常
throw表示此處抛出一個已定義的異常(可以是自定義異常、也可以是Java異常類)
2.3、try...catch
除了抛出異常外,我們還可以用try...catch方式在方法内部進行監視代碼try,如果出現異常就捕獲catch。
文法規則如下:
我們将可能發生異常的代碼放在try語句塊中,如果try語句塊中發生異常,那麼一個相應的異常對象就會被拋出(此時try語句塊中剩餘的語句會被忽略),異常對象抛出後會被catch捕獲并處理,catch後的括号()用于存放比對的異常類的執行個體,用于接收異常對象,在catch語句塊中就可編寫異常處理語句(比如調用異常對象的相關方法)。
另外,如果try語句塊中沒有發生異常,那麼try語句塊正常運作後會跳過catch語句塊,此時程式将從catch語句塊後的第一條語句開始執行。
代碼如下:
try {
// 編寫可能出現異常的代碼...
} catch (異常類 變量名) {
// 異常處理
}
另外,如果try語句塊中可能産生多個異常,那麼try語句塊後可跟多個catch代碼塊,如下所示:
try {
// 編寫可能出現異常的代碼...
} catch (異常類1 變量名) {
// 異常處理
} catch (異常類2 變量名) {
// 異常處理
}
...
有時我們也會這麼寫:
try {
// 編寫可能出現異常的代碼...
} catch (Exception e) { // Exception可以用于捕獲一切異常類型
e.printStackTrace(); // 列印異常棧資訊
}
綜上所述,try...catch方式使得發生異常的部分可以自己獨立完成異常的處理,程式仍可以往下執行。
備注:
當捕獲的多個異常類之間存在父子關系(繼承關系)時,捕獲異常時一般先捕獲子類,再捕獲父類。是以子類異常必須寫在父類異常的前面,否則子類捕獲不到。
try...catch後面的花括号{ }不可以省略(即使語句塊中隻有一行代碼),這與if...else語句可以省略花括号不一樣。
try語句塊裡聲明的變量屬于局部變量(這些局部變量隻在try塊内有效)
舉個例子:
我們編寫一個程式,要求使用者輸入一個合法價格,然後輸出打折後的價格。
這裡如果使用者輸入的價格低于0,則提醒使用者輸入的價格必須為正數。
如果使用者輸入的價格不是合法數值,則提醒使用者輸入價格的格式有誤。
代碼如下:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (true) {
try {
System.out.println("請輸入正确的價格(按0退出):");
String priceStr = sc.nextLine();
double price = Double.valueOf(priceStr);
if(price > 0) {
System.out.println("打折後價格為:" + price*0.75);
System.out.println("=====");
}else if(price == 0) {
System.out.println("程式正在退出...");
break;
}else {
System.out.println("請輸入正數!");
System.out.println("=====");
}
}catch (Exception e) {
System.out.println("您輸入的數值格式不正确!");
System.out.println("=====");
}
}
}
}
運作後的結果可以是:
請輸入正确的價格(按0退出):
666
打折後價格為:499.5
=====
請輸入正确的價格(按0退出):
-100
請輸入正數!
=====
請輸入正确的價格(按0退出):
abc
您輸入的數值格式不正确!
=====
請輸入正确的價格(按0退出):
0
程式正在退出...
Process finished with exit code 0
2.4、finally
finally關鍵字用于建立在try代碼塊後面執行的代碼塊。其特點是,無論是否有異常發生,finally代碼塊中的代碼總會被執行。
文法如下:
try {
// 可能發生異常的代碼
// ...
} catch(異常類1 變量1) {
// 異常處理子產品1
// ...
} catch(異常類2 變量2) {
// 異常處理子產品2
// ...
} finally{
// 具有收尾善後性質的語句
// ...
}
注意事項:
finally語句塊并不是強制要求的;
程式會先執行catch裡面的代碼,接着執行finally裡面的代碼,最後才執行catch塊中的return語句。
如果finally塊中有return語句,則catch塊中的return語句則不會被執行到