[英]What comes first - finally or catch block?
考慮以下測試用例:
public class Main {
static int a = 0;
public static void main(String[] args) {
try {
test();
System.out.println("---");
test2();
}
catch(Exception e) {
System.out.println(a + ": outer catch");
a++;
}
}
public static void test()
{
try {
throw new Exception();
}
catch (Exception e) {
System.out.println(a + ": inner catch");
a++;
}
finally {
System.out.println(a + ": finally");
a++;
}
}
public static void test2() throws Exception
{
try {
throw new Exception();
}
finally {
System.out.println(a + ": finally");
a++;
}
}
}
隨着輸出:
0: inner catch
1: finally
---
2: finally
3: outer catch
什么是為什么在test()
捕獲發生之前最終在test2()
發生的原因是另一種解釋?
關鍵點是:
try-(catch)-finally
塊中, finally
執行該特定try
塊的finally
try
中的另一個塊,而且每個嵌套的try
塊可以有自己的finally
,這對那些個人進行最后的try
塊 所以是的, finally
是finally
執行,但僅適用於它附加的try
塊。
所以給出以下代碼段:
try {
try {
throw null;
} finally {
System.out.println("Finally (inner)");
}
} catch (Throwable e) {
System.out.println("Catch (outer)");
}
打印( 如ideone.com上所示 ):
Finally (inner)
Catch (outer)
觀察:
(inner)
, Finally
是最后(無論是否有任何catch
成功) Catch (outer)
跟隨Finally (inner)
,但那是因為Finally (inner)
嵌套在(outer)
內的另一個 try
塊內 同樣,以下代碼段:
try {
try {
throw null;
} catch (Throwable e) {
System.out.println("Catch (inner)");
} finally {
System.out.println("Finally (inner)");
throw null;
}
} catch (Throwable e) {
System.out.println("Catch (outer)");
}
打印( 如ideone.com上所示 ):
Catch (inner)
Finally (inner)
Catch (outer)
因為test2()
中的try
塊沒有catch
塊,所以只有finally
塊。 代碼不會“跳回”到調用者陷入catch
然后“跳到” finally
繼續那里,就像你想象的那樣。
catch最終出現在同一個try-catch-finally范圍之前。
它test2在test2的try-catch-finally范圍內沒有捕獲,所以它在離開范圍之前完成了最終並落入了更高的catch。
因為finally
塊總是在退出范圍之前執行。 調用test2()
后的事件序列如下:
test2()
拋出異常 test2
沒有catch
塊,異常會傳播到調用者。 test2
有一個finally
塊,因此在從方法返回之前執行它。 catch
捕獲異常。 因為, 最后是在try..catch塊中執行的最后一個代碼,無論是拋出,拋出然后處理,還是根本不拋出異常。
實際上,最終不會被調用的唯一時間是,如果JVM在執行它之前退出,或者執行try代碼的線程被終止或中斷。
回應評論: Java描述終於
Note: If the JVM exits while the try or catch code is being executed,
那么finally塊可能不會執行。 同樣,如果執行try或catch代碼的線程被中斷或終止,則即使應用程序作為一個整體繼續,finally塊也可能無法執行。
但是你是正確的,因為拋出了一個ThreadDeath異常,我找不到太多關於來自sun的沖突信息的詳細信息。 這本身就是一個問題。
最后 (原諒雙關語)@brainimus,如果你在finally中並拋出異常,那么最后的代碼正在被執行,我的觀點是最終代碼沒有被執行的條件。
try - catch並最終用於避免由於在程序執行期間出現不需要的錯誤而導致程序終止的情況。
以下幾點很重要......
1)一個塊只有一次嘗試......一個塊的任意數量的catch語句,最后只有一個用於一個塊的語句
2)最后是可選的。
3)catch也是可選的但如果缺少catch語句則最終必須出現。
4)對應於子例外的所有捕獲必須出現在父異常的catch之前。
5)無論異常的發生如何,finally塊中出現的語句總是以一個排除的方式執行。
即如果遇到System.out.exit()語句,則程序會立即終止,因此在這種情況下最終無法執行。
注意:即使在try塊中出現一個return語句......然后也會執行finally中的代碼。
如果您通過方法代碼替換函數,您會得到:
public class Main {
static int a = 0;
public static void main(String[] args) {
try {
try {
throw new Exception();
}
catch (Exception e) {
// I catch only the *first* exception thrown
System.out.println(a + ": inner catch");
a++;
// let's go to the finally block
}
finally {
System.out.println(a + ": finally");
a++;
// we go on
}
System.out.println("---");
try {
throw new Exception();
}
finally {
// executed because at the same level
System.out.println(a + ": finally");
a++;
}
}
catch(Exception e) {
// I catch only the *second* exception thrown
System.out.println(a + ": outer catch");
a++;
}
}
第一個異常使catch塊執行,然后執行第一個finally塊。 由於第一個捕獲塊,它在外層看不到。 第二個異常由外層的catch塊攔截,但最終位於內層,最后執行。
首先執行try塊。 如果try塊中存在需要捕獲的異常,則執行Catch。 最后,無論是否存在異常,都會運行塊。 如果在try塊內有return語句,那么在try塊中返回之前,最后塊執行,然后在try塊中執行return。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.