目錄
- 1 方式1:try…catch...finally捕獲例外
- 1.1 try…catch代碼塊
- 1.2 finally 代碼塊
- 2 方式2:throws宣告拋出例外
- 2.1 throw關鍵字
- 2.3 throws關鍵字
例外處理方式一:在當前方法中直接用try…catch處理
例外處理方式二:在當前方法中不處理,throws 例外拋給呼叫者處理
1 方式1:try…catch...finally捕獲例外
1.1 try…catch代碼塊
try-catch的方式就是捕獲例外,
-
try:該代碼塊中撰寫可能產生例外的代碼,
-
catch:用來進行某種例外的捕獲,對捕獲到的例外進行處理,
格式:
//形式一:一個catch塊
try{
可能發生例外的代碼(沒有例外的代碼也可以放進來)
}catch(例外型別 例外名e){
處理例外的代碼(一般都是列印例外的資訊的陳述句)
}
//形式二:多個catch塊
try{
可能發生例外的代碼
}catch(例外型別 例外名e){
處理例外的代碼(一般都是列印例外的資訊的陳述句)
}catch(例外型別 例外名e){
處理例外的代碼(一般都是列印例外的資訊的陳述句)
}
...
catch(例外型別 例外名e){
處理例外的代碼(一般都是列印例外的資訊的陳述句)
}
try 和 catch 都不能單獨使用
注意:
- catch 中定義的例外變數的型別是根據 try 中拋出的例外來定義的;一般拋出什么型別的例外物件,就定義什么型別例外變數來接收這個例外物件
- try 中可能會拋出多個例外物件,就可以定義多個 catch 來分別處理這些例外物件
- try代碼中如果出現了例外,那么就不會繼續執行 try 中的代碼,找對應的匹配的catch分支執行,執行完畢后繼續執行try...cath之后的代碼
- try代碼中如果沒有出現例外,正常執行try中的代碼,不會執行catch中例外的處理邏輯,會執行執行try...catch之后的代碼
-
多個例外該如何處理呢
- 多個例外分別處理,一個例外對應一個try一個catch
- 多個例外一次捕獲多次處理,一個try多個catch
- 多個例外一次捕獲一次處理,只用一個try一個catch,定義一個范圍更大的父類例外物件
一般我們是使用一次捕獲多次處理方式,格式如下:
try{ 撰寫可能會出現例外的代碼 }catch(例外型別A e){ 處理例外的代碼 //記錄日志/列印例外資訊/繼續拋出例外 }catch(例外型別B e){ 處理例外的代碼 //記錄日志/列印例外資訊/繼續拋出例外 }...
注意:這種例外處理方式,要求多個catch中的例外不能相同,并且若catch中的多個例外之間有繼承關系,那么要求子類例外在上面的catch處理,父類例外在下面的catch處理;若無繼承關系,順序隨意,
演示如下:
public class ExceptionDemo {
public static void main(String[] args) {
try {
show(1);
}catch (NullPointerException e) {
System.out.println("處理空指標例外");
}catch (ArrayIndexOutOfBoundsException e) {
System.out.println("處理陣列下標越界例外");
}
System.out.println("程式結束!");
}
private static void show(int a) {
if (a == 0) {
int[] arr = new int[0];
System.out.println(arr[1]);
}else {
int[] arr = null;
System.out.println(arr.length);
}
}
}
1.2 finally 代碼塊
finally:有一些特定的代碼無論例外是否發生,都需要執行,另外,因為例外會引發程式跳轉,導致有些陳述句執行不到,而finally就是解決這個問題的,在finally代碼塊中存放的代碼都是一定會被執行的,
什么代碼必須最終執行?
當我們在try陳述句塊中打開了一些物理資源(磁盤檔案/網路連接/資料庫連接等),我們都得在使用完之后關閉打開的資源,
格式:
//形式一:try...catch...finally
try{
可能發生例外的代碼
}catch(例外型別 例外名e){
處理例外的代碼(一般都是列印例外的資訊的陳述句)
}
...
catch(例外型別 例外名e){
處理例外的代碼(一般都是列印例外的資訊的陳述句)
}
finally{
無論try中是否有例外,也不管catch是否可以捕獲例外,也不管try和catch中是不是有return,都要執行的部分
}
//形式二:try...finally(一般不用)
try{
可能發生例外的代碼
}finally{
無論try中是否有例外,也不管是不是有return,都要執行的部分
}
注意:finally不能單獨使用
finally代碼參考如下:
public class ExceptionDemo2 {
public static void main(String[] args) {
try {
show(1);
}catch (NullPointerException e) {
System.out.println("處理空指標例外");
}catch (ArrayIndexOutOfBoundsException e) {
System.out.println("處理陣列下標越界例外");
}finally {
System.out.println("finally中的方法一定會執行");
}
System.out.println("程式結束!");
}
private static void show(int a) {
if (a == 0) {
int[] arr = new int[0];
System.out.println(arr[1]);
}else {
int[] arr = null;
System.out.println(arr.length);
}
}
}
當只有在try或者catch中呼叫退出JVM的相關方法,finally才不會執行,否則finally永遠會執行,
finally與return混用的情況(避免使用)
- 不管try中是否發生例外,也不管catch是否可以捕獲例外,也無論try或catch中是否有return陳述句,finally中的代碼都必須執行
- 如果finally中有return,就從finally塊的的return回傳,
- 如果finally中沒有return,那么先把try或catch中該執行的執行完(包括把回傳值的結果放到要帶回呼叫處的運算元堆疊的位置)
演示代碼:
public class ExceptionDemo3 {
public static void main(String[] args) {
int num = getNum(4);
System.out.println(num); // 0
}
private static int getNum(int a){
int result = 10;
try{
System.out.println(a/0);
if(a > 0){
result = 20;
return result;
}else if(a < 0){
result = -20;
return result;
}else{
return result;
}
}catch(Exception e){
System.out.println("exception");
result = 0;
return result;
}finally{
result = 30;
System.out.println("finally");
// return result;//如果有這句,結果就變成30
}
}
}
return 值; 陳述句有兩個動作:
(1)把回傳值放到”運算元堆疊“中
(2)結束當前方法的執行,把“運算元堆疊”中的值會回傳給呼叫處
如果finally中沒有return,finally中的陳述句會執行,但是不影響最終的回傳值
即try、catch中的return陳述句兩步拆開走,先把把回傳值放到“運算元堆疊”中,然后走finally中的陳述句,最后結束當前方法,把這個“運算元堆疊”中的值回傳給呼叫處
2 方式2:throws宣告拋出例外
2.1 throw關鍵字
在撰寫程式時,我們必須要考慮程式出現問題的情況,比如,在定義方法時,方法需要接受引數,那么,當呼叫方法使用接受到的引數時,首先需要先對引數進行合法的判斷,資料若不合法,就應該告訴呼叫者,傳遞合法的資料進來,這時需要使用拋出例外的方式來告訴呼叫者,
例外的物件的創建和拋出有兩種方式:
(1)JVM創建并拋出
(2)程式員new出來,然后由throw拋出,
在java中,提供了一個throw關鍵字,它用來拋出一個指定的例外物件:
-
創建一個例外物件,封裝一些提示資訊(資訊可以自己撰寫)
-
通過關鍵字throw,throw 例外物件,將這個例外物件告知給呼叫者
throw 用在方法內,用來拋出一個例外物件,將這個例外物件傳遞到呼叫者處,并結束當前方法的執行,
注意事項:
throw關鍵字必須寫在方法內部
throw關鍵字后邊創建的例外物件,必須是Exception或Exception的子類物件
throw關鍵字后邊創建的例外物件:
(1) 如果是運行期例外,那么我們不用處理這個例外,交給JVM處理,默認處理方式就是中斷處理
(2) 如果是編譯期例外,那么我們就必須處理這個例外,要么throws繼續拋出交給上層呼叫者處理,要么try...catch自己處理
使用格式:
throw new 例外類名([引數]);
例如:
throw new Exception();
throw new ClassNotFoundException("型別不存在!");
代碼示例:
public class ThrowsDemo {
public static void main(String[] args) throws ClassNotFoundException, FileNotFoundException {
method01(0);
}
private static void method01(int a) throws ClassNotFoundException, FileNotFoundException {
if (a == 0){
throw new ClassNotFoundException("型別不存在!");
}else {
throw new FileNotFoundException("檔案不存在!");
}
}
}
那么對于呼叫者來說,該怎么處理呢?
對于運行期例外可以不做處理;對于編譯期例外:一種是使用 try...catch 進行捕獲處理,另一種就是使用
throws關鍵字繼續將例外宣告出去,由方法呼叫者處理
2.3 throws關鍵字
宣告例外:將問題標識出來,報告給呼叫者,如果方法內拋出了編譯期例外,而沒有捕獲處理,那么必須通過throws關鍵字進行宣告,讓呼叫者去處理,
關鍵字throws用在方法宣告上,用于表示當前方法不處理例外,而是提醒該方法的呼叫者來處理例外
宣告例外格式:
修飾符 回傳值型別 方法名(引數) throws xxxException, yyyException...{
...
}
宣告例外的代碼示例:
public class ThrowsDemo {
public static void main(String[] args) throws NullPointerException, ArrayIndexOutOfBoundsException {
int[] arr = null;
method01(arr);
}
private static void method01(int[] arr) throws NullPointerException, ArrayIndexOutOfBoundsException {
//Objects.requireNonNull(arr);
if (arr.length==0){
throw new ArrayIndexOutOfBoundsException("越界了");
}
if (arr == null){
throw new NullPointerException();
}
}
}
注意事項:
- throws關鍵字必須寫在方法宣告處
- throws關鍵字后邊宣告的例外類名必須是Exception或Exception的子類
一般方法內部拋出什么例外型別,就宣告什么例外物件 - 如果方法內部拋出了多個例外物件,那么在throws后面可以寫多個例外類,用逗號隔開,
如果拋出的多個例外物件有子父類關系,那么我們宣告父類例外即可 - 如果呼叫了一個宣告拋出編譯期例外的方法,那么我們就必須處理這個例外物件:
a.可以使用throws繼續宣告拋出這個例外,最終交由JVM處理 --> 中斷處理
b.可以使用try...catch自己處理這個例外 - 運行期例外可以不處理,即不捕獲也不宣告拋出,交給JVM處理(中斷))
- 如果父類拋出了多個例外,子類重寫父類方法時,拋出和父類相同的例外或者是父類例外的子類或者不拋出例外,
- 父類方法沒有拋出例外,子類重寫父類該方法時也不可拋出例外,如果子類產生例外,只能捕獲處理,不能宣告拋出
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/36337.html
標籤:Java
下一篇:JAVA 9 新特性
