天天看點

「Java·異常處理語句」throws/throw、try...catch、finally

作者:是啊超ya

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語句則不會被執行到

繼續閱讀