這道面試題,出錯(cuò)率90%
關(guān)注“Java后端技術(shù)全棧”
大多數(shù)公司針對初級、中級都會(huì)有筆試的這個(gè)環(huán)節(jié),甚至很多高級面試也存在筆試環(huán)節(jié)。對于筆試大家千萬不要掉以輕心,筆試題做不好,很有可能面試就黃了或者隨便找個(gè)面試官應(yīng)付一下就可以回去等通知了。
今天我們分享的這個(gè)面試題,出現(xiàn)的頻率是相當(dāng)高。
案例
我們先上代碼:
public?class?TryFinallyDemo?{
????public?static?void?main(String[]?args)?{
????????TryFinallyDemo?tryFinallyDemo?=?new?TryFinallyDemo();
????????System.out.println(tryFinallyDemo.test());
????}
????public?String?test()?{
????????String?name?=?"蒼老師";
????????try?{
????????????return?name;
????????}?finally?{
????????????name?=?"小澤";
????????}
????}
}
運(yùn)行上面這段代碼,輸出什么?
是"蒼老師"還是"小澤"?
其實(shí),對于java開發(fā)者來說,finally已經(jīng)是老熟人了。
有時(shí)候,程序在try塊里打開了一些物力資源(比如:數(shù)據(jù)庫連接,網(wǎng)絡(luò)連接、磁盤文件等),這些物力資源都是必須要我們手動(dòng)回收。
那就該它出場了---finally。
一個(gè)完整的java異常處理結(jié)構(gòu)如下:
public?void?test(){
????try{
????????//業(yè)務(wù)代碼
????}catch(SubException?e1){
???????//異常處理模塊1
????}catch(SubException?e2){
???????//異常處理模塊1
????}finally{
????????//資源回收模塊
????}
}
為了保證一定能回收try模塊中打開的物力資源,一場極致提供了finally模塊。不管try模塊中的代碼是否異常,也不管是哪一個(gè)catch被執(zhí)行,甚至try或者catch模塊中執(zhí)行了return語句,finally模塊總會(huì)被執(zhí)行。
try、catch、finally三者的組合關(guān)系為:

在前面已經(jīng)提到了,不管try里是否有異常,不管try或者catch是否有return語句,finally里的代碼塊會(huì)執(zhí)行。
如果在try模塊沒有發(fā)生異常,那么代碼正常執(zhí)行完畢,在執(zhí)行finally模塊。 如果try模塊發(fā)生異常并且被catch模塊捕獲了,那么在catch模塊內(nèi)的代碼執(zhí)行結(jié)束后再執(zhí)行finally模塊。 如果try模塊中有異常并且沒有catch模塊或者沒有被catch模塊捕獲到,那么在異常被跑出去之前執(zhí)行finally模塊。
異常相關(guān)推薦這篇文章:
于是乎,很多人就認(rèn)為答案是:小澤
運(yùn)行代碼,輸出的居然是:蒼老師
是不是很懵逼?為什么是“蒼老師”?

不著急,下面我們來好好分析分析。
我們先通過javac編譯,再通過javap命令查看看字節(jié)碼內(nèi)容。內(nèi)容如下:

整個(gè)過程
第一步:將"蒼老師"放入操作棧中,然后將操作數(shù)棧中的數(shù)據(jù)保存在本地變量1中,將本地變量1放入操作數(shù)棧中,然后將操作數(shù)棧中的數(shù)據(jù)保存在本地變量2中。

第二步:將“小澤”放入操作棧中,然后將操作數(shù)棧中的數(shù)據(jù)保存到本地變量1中。

第三步:將本地變量2放入操作數(shù)棧中,將操作數(shù)棧中的數(shù)據(jù)返回。

所以上面的面試題,最終返回的是蒼老師。
另外,如果在try模塊出現(xiàn)異常,那么也是在finally模塊執(zhí)行完了再向外面拋出異常的。
public?String?test()?{
????????String?name?=?"蒼老師";
????????try?{
????????????int?a?=?1/0;
????????????return?name;
????????}?finally?{
????????????System.out.println("finally");
????????????name?=?"小澤";
????????}
?}
調(diào)用這個(gè)方法必然會(huì)出現(xiàn)異常:

從輸出日志中可以看出,異常時(shí)在finally模塊后執(zhí)行。
例外
如果我們在try模塊代碼中有下面這行代碼,finally模塊就不會(huì)執(zhí)行了。
System.exit(0);
總結(jié)
本文講述了finally如何使用。以及哪些情況下finally模塊會(huì)執(zhí)行,哪些情況下不會(huì)被執(zhí)行,finally模塊和try模塊的關(guān)系。希望大家不管是在工作中還是面試都能輕松應(yīng)對。
沒有學(xué)不好的技術(shù),只有不愛學(xué)習(xí)的人~
