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也是如此