來源:https://blog.csdn.net/lwd512768098/article/details/114728720
昨晚參加一個面試,被問到try catch finally相關的知識,雖然之前了解過其中奇怪的用法,特別有return的情況,但是由於時間久遠,完全忘了,導致這個問題回答不是很好,只是知道finally無論是否發生異常都會執行的(但是忘了含有return的情況是怎麽處理的了),finally常常用來關閉一些資源,像檔,連線等。
finally終究執行
我們先來驗證一下finally終究執行
publicstaticinttest() {
int i = 1;
try {
i++;
} finally {
System.out.println("finally yeah!");
}
return i;
}
publicstaticvoidmain(String[] args) {
System.out.println(test());
}
輸出為
publicstaticinttest() {
int i = 1;
try {
i++;
thrownew Exception();
} catch (Exception e) {
System.out.println("Exception yeah!");
} finally {
System.out.println("finally yeah!");
}
return i;
}
publicstaticvoidmain(String[] args) {
System.out.println(test());
}
從上面兩個例子中我們可以看到,無論是正確執行try塊還是在try塊發生了異常,finally塊都是被執行的
帶有return的情況
finally不帶return的情況
對於return情況的話,只要記住一句話就行,如果finally裏面有return, 那麽就會覆蓋try塊或者catch裏面的return內容,否則的話,在執行finally的內容之前(try塊或者catch裏面有return語句),會計算好try或者catch裏面的return運算式的值,然後保存到另一個局部變量,當執行fianlly的時候,會重新載入這個局部變量作為返回值,因此在finally的操作不會影響返回值,下面我們字節碼來看看內部的工作原理。
publicstaticinttest() {
int i = 1;
try {
i++;
return i;
} finally {
i++;
System.out.println("finally yeah!");
}
}
publicstaticvoidmain(String[] args) {
System.out.println(test());
}
第一個問題:在try塊中含有return語句,你覺得finally語句還有執行麽?
第二個問題:最終結果是多少?
從上面可以看到,盡管try塊裏面有return, 但是finally塊仍然執行了,你肯定會好奇,那為啥返回值是2呢,finally裏面不是還進行了i++麽。
簡單分析一下,從結果看,finally仍然執行,說明try的return語句是還沒執行的,下面我們看看字節碼。
上面圖片已經標註很清楚了,如果還不明白的話,可以先去看一下這幾個字節碼命令,還是挺簡單的,註意的是,JVM操作都是基於運算元棧的。
總結一下,總體的意思就是,當執行完try塊的時候,會計算return運算式的值,然後把這個返回值存在另一個臨時變量裏面,最後返回的時候會重新讀取存放的變量,因此在finally後面無論如何修改,都不會影響返回值(除非finally裏面含有return,這個我們在下面討論)
finally帶有return
上面的情況是try或者catch裏面含有return,finally沒有return, 那麽fianlly裏面如何修改返回值是不會影響最後的返回值。下面討論finally裏面含有return的情況。
publicstaticinttest() {
int i = 1;
try {
i++;
return i;
} finally {
i++;
System.out.println("finally yeah!");
return i;
}
}
publicstaticvoidmain(String[] args) {
System.out.println(test());
}
相信各位能夠正常猜出結果了
沒錯,返回了3,說明finally對i的修過是其效果的,我們從字節碼看看原因:
從上圖可以看到,在返回之前,載入的是0槽位的變量,這時0槽位的變量的值是3,1槽位的變量是2,所以返回的3。
由上可以得知,當finally中含有return的時候,會覆蓋之前try或者catch(上面沒有貼出實驗,需要驗證的可以去驗證,作者本人是驗證過了)裏面的返回值的
try, catch, finally均沒有return語句
這種情況比較簡單,跟finally含有return類似
publicstaticinttest() {
int i = 1;
try {
i++;
} finally {
i++;
System.out.println("finally yeah!");
}
return i;
}
publicstaticvoidmain(String[] args) {
System.out.println(test());
}
總結
這裏總結一下, 只要finally裏面沒有return語句,那麽返回值就由try或者catch的return語句決定,否則由finally的return語句決定