1. 程式人生 > 其它 >Day27---學習Java第二彈

Day27---學習Java第二彈

2021-08-06

Java異常方法

2. try-catch-finally語句

try-catch語句還可以包括第三部分,就是finally子句。它表示無論是否出現異常,都應當執行的內容。try-catch-finally語句的一般語法形式為:

                try {
            // 可能會發生異常的程式程式碼
        } catch (Type1 id1) {
            // 捕獲並處理try丟擲的異常型別Type1
        } catch (Type2 id2) {
            // 捕獲並處理try丟擲的異常型別Type2
} finally { // 無論是否發生異常,都將執行的語句塊 }

例5帶finally子句的異常處理程式。

public class TestException {
    public static void main(String args[]) {
        int i = 0;
        String greetings[] = { " Hello world !", " Hello World !! ",
                " HELLO WORLD !!!" };
        while (i < 4) {
            
try { // 特別注意迴圈控制變數i的設計,避免造成無限迴圈 System.out.println(greetings[i++]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("陣列下標越界異常"); } finally { System.out.println("--------------------------"); } } } }

執行結果:

Hello world !

--------------------------

Hello World !!

--------------------------

HELLO WORLD !!!

--------------------------

陣列下標越界異常

--------------------------

在例5中,請特別注意try子句中語句塊的設計,如果設計為如下,將會出現死迴圈。如果設計為:

try {
      System.out.println (greetings[i]); i++;
}

小結:

try 塊:用於捕獲異常。其後可接零個或多個catch塊,如果沒有catch塊,則必須跟一個finally塊。

catch 塊:用於處理try捕獲到的異常。

finally 塊:無論是否捕獲或處理異常,finally塊裡的語句都會被執行。當在try塊或catch塊中遇到return語句時,

finally語句塊將在方法返回之前被執行。在以下4種特殊情況下,finally塊不會被執行:

1)在finally語句塊中發生了異常

2)在前面的程式碼中用了System.exit()退出程式。

3)程式所在的執行緒死亡。

4)關閉CPU。

3. try-catch-finally 規則(異常處理語句的語法規則):

1) 必須在 try 之後新增 catch 或 finally 塊。try 塊後可同時接 catch 和 finally 塊,但至少有一個塊。

2) 必須遵循塊順序:若程式碼同時使用 catch 和 finally 塊,則必須將 catch 塊放在 try 塊之後。

3) catch 塊與相應的異常類的型別相關。

4) 一個 try 塊可能有多個 catch 塊。若如此,則執行第一個匹配塊。即Java虛擬機器會把實際丟擲的異常物件依次和各個

catch程式碼塊宣告的異常型別匹配,如果異常物件為某個異常型別或其子類的例項,就執行這個catch程式碼塊,不會再執行其他的 catch程式碼塊

5) 可巢狀 try-catch-finally 結構。

6) 在 try-catch-finally 結構中,可重新丟擲異常。

7) 除了下列情況,總將執行 finally 做為結束:JVM 過早終止(呼叫 System.exit(int));

在 finally 塊中丟擲一個未處理的異常;計算機斷電、失火、或遭遇病毒攻擊。

4. try、catch、finally語句塊的執行順序:

1)當try沒有捕獲到異常時:try語句塊中的語句逐一被執行,程式將跳過catch語句塊,執行finally語句塊和其後的語句;

2)當try捕獲到異常,catch語句塊裡沒有處理此異常的情況:當try語句塊裡的某條語句出現異常時,

而沒有處理此異常的catch語句塊時,此異常將會拋給JVM處理,finally語句塊裡的語句還是會被執行,但finally語句塊後的語句不會被執行;

3)當try捕獲到異常,catch語句塊裡有處理此異常的情況:在try語句塊中是按照順序來執行的,

當執行到某一條語句出現異常時,程式將跳到catch語句塊,並與catch語句塊逐一匹配,找到與之對應的處理程式,

其他的catch語句塊將不會被執行,而try語句塊中,出現異常之後的語句也不會被執行,catch語句塊執行完後,

執行finally語句塊裡的語句,最後執行finally語句塊後的語句;

Throws丟擲異常的規則:

1) 如果是不可查異常(unchecked exception),即Error、RuntimeException或它們的子類,

那麼可以不使用throws關鍵字來宣告要丟擲的異常,編譯仍能順利通過,但在執行時會被系統丟擲。

2)必須宣告方法可丟擲的任何可查異常(checked exception)。即如果一個方法可能出現受可查異常,

要麼用try-catch語句捕獲,要麼用throws子句宣告將它丟擲,否則會導致編譯錯誤

3)僅當丟擲了異常,該方法的呼叫者才必須處理或者重新丟擲該異常。當方法的呼叫者無力處理該異常的時候,應該繼續丟擲,而不是囫圇吞棗。

4)呼叫方法必須遵循任何可查異常的處理和宣告規則。若覆蓋一個方法,則不能宣告與覆蓋方法不同的異常。

宣告的任何異常必須是被覆蓋方法所宣告異常的同類或子類。

void method1() throws IOException{}  //合法  
 
//編譯錯誤,必須捕獲或宣告丟擲IOException  
void method2(){  
  method1();  
}  
 
//合法,宣告丟擲IOException  
void method3()throws IOException {  
  method1();  
}  
 
//合法,宣告丟擲Exception,IOException是Exception的子類  
void method4()throws Exception {  
  method1();  
}  
 
//合法,捕獲IOException  
void method5(){  
 try{  
    method1();  
 }catch(IOException e){…}  
}  
 
//編譯錯誤,必須捕獲或宣告丟擲Exception  
void method6(){  
  try{  
    method1();  
  }catch(IOException e){throw new Exception();}  
}  
 
//合法,宣告丟擲Exception  
void method7()throws Exception{  
 try{  
  method1();  
 }catch(IOException e){throw new Exception();}  
} 

判斷一個方法可能會出現異常的依據如下:

1)方法中有throw語句。例如,以上method7()方法的catch程式碼塊有throw語句。

2)呼叫了其他方法,其他方法用throws子句宣告丟擲某種異常。例如,method3()方法呼叫了method1()方法,

method1()方法宣告丟擲IOException,因此,在method3()方法中可能會出現IOException。


---------------------------------------------------------------------------------------------------------------------------

注意:

1、Throw (是 catch 中還是非 catch 中)後面不能再跟其他程式碼塊了 ,否則編譯不能通過,

例如把return和throw放在一起,IDEA直接提示錯誤:"Unreachablestatement" .

2、但可以在finally語句塊有return語句,finally語句塊成功騙過編譯器讓throw和return兩者並存

finally如果有return會覆蓋catch裡的throw,同樣如果finally裡有throw會覆蓋catch裡的return。

進而如果catch裡和finally都有return, finally中的return會覆蓋catch中的。throw也是如此