![Java高概率面試題目—finally(看完這篇文章,唬住面試官)](http://p2.ttnews.xyz/loading.gif)
在Java面試中關於finally的面試題目出現的概率非常高,而且一旦面試官問起絕不會是蜻蜓點水,而是會向你發起層層遞進地“連環問”,並且回答這系列問題常常需要代碼的輔助,可謂考驗基礎的面試利題。究竟面試官會問些什麼呢?應試者又該怎樣完美回答呢?今天小編就帶著猿猿們親身體驗一場finally面試,希望對你有幫助。
前提需要了解:當發生異常之後,異常之後的代碼不會執行,會到catch塊中執行,但是catch之後的代碼會執行,簡單的例子:
public static String test(){
try {
int i=1/0;
System.out.println("error open");//上面發生異常,所以永遠不會走這裡
return "1";
} catch (ArithmeticException e) {
System.out.println("error");
}
System.out.println("try..catch...finish");
return "finish";
}
結果:
error
try..catch...finish
面試官題目
什麼時候用到finally呢?finally語句在try或catch中的return語句執行之後,還是return返回之前執行呢?
考點分析
這個題目也是考查異常相關的。對於這個題目,我們通過代碼來驗證我們的答案,因為有異議的知識點,代碼是最有說服力的。對於編程,希望你記住“不與人爭辯,一切用代碼說話”。
回答
什麼時候用到finally呢?
某些事物(除內存外)在異常處理完後需要恢復到原始狀態,如:開啟的文件,網絡連接等。
finally語句在try或catch中的return語句執行之後,還是return返回之前執行呢?
這個問題是一個很經典的問題,經常被面試官問,如果自己不去實驗一下,可能判斷就會出錯。我們結合代碼來分析一下。
下面我們通過4個demo來得出最終結論。
1
private static int test1() {
int i = 1;
try {
System.out.println("try...");
return i += 10;
} catch (Exception e) {
System.out.println("catch...");
} finally {
i++;
System.out.println("finally...");
System.out.println("i=" + i);
}
return i;
}
執行結果:
try...
finally...
i=12
test1:11
總結:finally代碼塊是在try代碼塊中的return語句執行之後,返回之前執行的。
2
private static int test2() {
int i = 1;
try {
System.out.println("try...");
return i += 10;
} catch (Exception e) {
System.out.println("catch...");
} finally {
i++;
System.out.println("finally...");
System.out.println("i=" + i);
return i;
}
}
執行結果:
test2:12
try...
finally...
i=12
總結:finally代碼塊中的return語句覆蓋try代碼塊中的return語句。
3
private static Map
Map
map.put("KEY", "INIT");
try {
System.out.println("try...");
map.put("KEY", "TRY");
return map;
} catch (Exception e) {
System.out.println("catch...");
map.put("KEY", "CATCH");
} finally {
System.out.println("finally...");
map.put("KEY", "FINALLY");
map = null;
}
return map;
}
執行結果:
try...
FINALLY
finally...
總結: 如果finally語句中沒有return語句覆蓋返回值,那麼原來的返回值可能因為finally裡的修改而改變也可能不變。傳值類型的返回值:不變;傳址類型的返回值:會變。
這裡引入來一個新的問題,怎麼判斷一個變量是傳值還是傳址?傳值:8種基本數據類型及其包裝類,字符常量。傳址:數組和對象。
4
private static int test4() {
int i = 1;
try {
System.out.println("try...");
i = i / 0;
return i += 10;
} catch (Exception e) {
System.out.println("catch...");
return i;
} finally {
i++;
System.out.println("finally...");
System.out.println("i=" + i);
}
}
執行結果:
try...
catch...
finally...
i=2
1
總結: try代碼塊中的return語句在異常的情況下不會被執行,這樣具體返回哪個看情況;catch中的return執行情況與未發生異常時try中return的執行情況完全一樣。
- 第五種情況:
private int test5() {
int i = 1;
try {
System.out.println("try...");
i = i / 0;
return i += 10;
} catch (Exception e) {
System.out.println("catch...");
return i;
} finally {
i++;
System.out.println("finally...");
System.out.println("i=" + i);
return i;
}
}
try...
catch...
finally...
i=2
2
總結:finally代碼塊中的return語句覆蓋try代碼塊中的return語句。
彙總
根據上面的分析,咱們來彙總一下答案:
- try語句沒有被執行,如在try語句之前就返回了,這樣finally語句就不會執行;因此說明了finally語句被執行的必要而非充分條件是:相應的try語句一定被執行到。
- 如果在try代碼塊中執行System.exit(0)語句;那麼將終止Java虛擬機JVM,因此,finally語句也不會被執行到。
- finally塊的語句在try或catch中的return語句執行之後返回之前執行且finally裡的修改語句可能影響也可能不影響try或catch中return已經確定的返回值,如果返回值類型為傳址類型,則影響;傳值類型,則不影響。若finally裡也有return語句則覆蓋try或catch中的return語句直接返回。
閱讀更多 程序員界的彭于晏 的文章