一、前言
因為這次面試有問到一些同學finally的問題,發現自己這塊好像有點記不太清楚了,有的點可能還給人家說錯了,一度弄得場面有些尷尬。所以說這篇文章深入研究一下finally的執行情況和返回值的情況。
二、finally一定會執行嗎?
先給答案:肯定不是。
我們可以看兩種情況:
1.在執行try塊之前直接return,我們發現finally塊是不會執行的
public class TryCatchTest {
private static int total() {
int i = 11;
if (i == 11) {
return i;
}
try {
System.out.println("執行try");
} finally {
System.out.println("執行finally");
}
return 0;
}
public static void main(String[] args) {
System.out.println("執行main:" + total());
}
}
輸出結果:
執行main:11
復制程式碼
2.在執行try塊之前制造一個錯誤,直接爆紅
public class TryCatchTest {
private static int total() {
return 1 / 0;
try {
System.out.println("執行try");
} finally {
System.out.println("執行finally");
}
return 0;
}
public static void main(String[] args) {
System.out.println("執行main:" + total());
}
}
綜上我們看出, 如果程式連try塊都執行不到,那麽finally塊自然就不會執行到了 。
不過這裏有的同學就會問:如果執行了try塊,finally塊一定會執行嗎?有的同學答案就是一定會,其實非然,看看下面的例子吧:
public class TryCatchTest {
private static int total() {
try {
System.out.println("執行try");
System.exit(0);
} catch (Exception e) {
System.out.println("執行catch");
} finally {
System.out.println("執行finally");
}
return 0;
}
public static void main(String[] args) {
System.out.println("執行main:" + total());
}
}
輸出結果:
執行try
我們在執行try塊之中結束jvm,就沒事了,都不執行了。當然這個情況是比較極端的,記住就行,沒事不要亂整這個。最後總結一下: 不管是給try塊中造了個異常,還是在try塊中進行return,我們發現finally塊還是會執行的。因為例外處理設計初衷就是讓finally塊始終執行 。這個總結在finally的執行時機得到證明。
三、finally執行時機探討
首先看常規情況:
public class TryCatchTest {
private static int total() {
try {
System.out.println("執行try");
return 11;
} finally {
System.out.println("執行finally");
}
}
public static void main(String[] args) {
System.out.println("執行main:" + total());
}
}
輸出結果:
執行try
執行finally
執行main:11
分析一下,不難得出在這個例子中 finally塊執行在try塊的return之前 。我們給try塊中造一個異常:
public class TryCatchTest {
private static int total() {
try {
System.out.println("執行try");
return 1 / 0;
} catch (Exception e) {
System.out.println("執行catch");
return 11;
} finally {
System.out.println("執行finally");
}
}
public static void main(String[] args) {
System.out.println("執行main:" + total());
}
}
輸出結果:
執行try
執行catch
執行finally
執行main:11
同樣的, finally執行在catch塊return的執行前 。
四、finally塊中的返回值
1.finally塊不含返回值,但是做改變變量值的操作
看一個例子:
public class TryCatchTest {
private static int total() {
int i = 0;
try {
System.out.println("執行try:" + i);
return i;
} finally {
++i;
System.out.println("執行finally:" + i);
}
}
public static void main(String[] args) {
System.out.println("執行main:" + total());
}
}
輸出結果:
執行try:0
執行finally:1
執行main:0
如果看完前面分析,會發現跟想象的不太一樣。我們經過前面的分析,finally塊的執行時機應該是return之前,那理論上我們應該先
++i
使得
i等於1
,在執行
return i;
自然會返回1。
可是結果卻返回了0,這是因為Java程式會把try或者catch塊中的返回值保留,也就是暫時的確認了返回值,然後再去執行finally程式碼塊中的語句。等到finally程式碼塊執行完畢後,如果finally塊中沒有返回值的話,就把之前保留的返回值返回出去。
2.finally中含有返回值
範例1:
public class TryCatchTest {
private static int total() {
try {
System.out.println("執行try");
return 1;
} finally {
System.out.println("執行finally");
return 2;
}
}
public static void main(String[] args) {
System.out.println("執行main:" + total());
}
}
輸出結果:
執行try
執行finally
執行main:2
範例2:
public class TryCatchTest {
private static int total() {
int i = 1;
try {
System.out.println("執行try:" + i);
return i;
} finally {
++i;
System.out.println("執行finally:" + i);
return i;
}
}
public static void main(String[] args) {
System.out.println("執行main:" + total());
}
}
輸出結果:
執行try:1
執行finally:2
執行main:2
範例3:
public class TryCatchTest {
private static int total() {
int i = 1;
try {
System.out.println("執行try:" + i);
} finally {
++i;
System.out.println("執行finally:" + i);
}
return i;
}
public static void main(String[] args) {
System.out.println("執行main:" + total());
}
}
執行結果:
執行try:1
執行finally:2
執行main:2
這三個範例都說明了一點,在分析含有finally塊的方法返回值時,要對於return出現的地方進行具體分析。 在finally塊中進行return操作的話,則方法整體的返回值就是finally塊中的return返回值。如果在finally塊之後的方法內return,則return的值就是進行完上面的操作後的return值。
來源:juejin.im/post/5ec2993fe51d45209d437387
>>
END
精品資料,超贊福利,免費領
微信掃碼/長按辨識 添加【技術交流群】
群內每天分享精品學習資料
最近開發整理了一個用於速刷面試題的小程式;其中收錄了上千道常見面試題及答案(包含基礎、並行、JVM、MySQL、Redis、Spring、SpringMVC、SpringBoot、SpringCloud、訊息佇列等多個型別),歡迎您的使用。
👇👇
👇點選"閱讀原文",獲取更多資料(持續更新中)