我們經常會使用try/catch/finally語句塊。當然,return關鍵字使用也是很平常的事,但是不知道大家有沒有注意個這樣乙個問題。當在try語句塊裡面使用return語句,在finally裡面去修改return所要返回的內容會出現什麼情況。首先,我們知道return是結束方法的標誌,一旦方法執行到return語句就將返回不再往下執行。其次,我們也知道,finally裡面的語句是無論方法怎樣執行,最後都要執行finally裡面的語句。那麼究竟是先執行return還是finally呢?下面通過兩個小實驗來解決這個問題。
首先看第乙個例子:
public
class
testtrycatch
public
intfun
() catch
(exception e)finally}}
輸出結果:10
ok很簡單的乙個例子,建立了乙個方法fun,在方法裡使用try/catch語句,方法要求返回值型別為int型。在try裡面放回i,這個時候是10,但是在finally裡面將i值修改為20。我們看到結果是10,好像是return先執行。那麼接下來再看另乙個例子:
public
class
testtrycatch
public
stringbuilder fun
() catch
(exception e)finally}}
輸出結果:hellowordfinally
看結果似乎有點出乎意料了,因為這次finally裡面修改的內容生效了。看**其實差別不大,只是把返回值型別修改為stringbuilder了。那麼這是為什麼呢?下面就為大家解釋一下其中到底是怎麼執行的。
首先,拿第乙個例子來說,可以在main方法裡實現這樣一條語句:int result = test.fun();我們知道這樣做是沒有問題的,但是大家都知道「=」號賦值是常量賦值。但是,方法的存放位址和常量的存放位址是不一樣的,方法的存放在**區的。上面我們把乙個方法賦值給乙個int型也沒有報錯。那是因為在宣告方法是我們宣告了返回值型別。那麼編譯器就會在**的最前端預留一段返回值型別的記憶體。執行return的時候,就會把返回的內容寫入到這段記憶體中
這樣,執行「=」號賦值的時候,就能在記憶體中匹配到相同的型別。賦值便能成功。
弄清楚上面的道理之後,再來解釋最開始提出的問題就容易多了。在執行了return之後,返回的值已經被寫入到那段記憶體中了,finally再修改i的值,只是修改了後面**段的i值,對返回段記憶體沒有影響。至於第二個例子,再看下面這張圖你就會明白。
我們可以看到,當返回值不是基本資料型別的時候,其是指向一段記憶體的,return將返回段指向一段記憶體,但是**段的s依然是指向的同一段記憶體位址,所以當s修改它指向記憶體中的值的時候,其實也就修改了返回段指向記憶體中的值,所以最終的值改變了。
到底返回值變不變可以簡單的這麼記憶:當finally呼叫的任何可變api,會修改返回值;當finally呼叫任何的不可變api,對返回值沒有影響。
總結一下:其實return與finally並沒有明顯的誰強誰弱。在執行時,是return語句先把返回值寫入但記憶體中,然後停下來等待finally語句塊執行完,return再執行後面的一段。
文章**:
Java中finally與return的執行順序
finally不會執行的兩種情況 1.finally對應的try塊語句還沒被執行到就返回了2.finally對應的try塊語句中有system.exit 這樣的語句 finally塊的語句在try或catch中的return語句 執行之後返回之前執行 若finally裡也有return語句,則 覆蓋...
return和finally執行順序
public class test public static int tt catch exception e finally system.out.println finally system.out.println come here return b 執行結果 yesb 25 111 fin...
不能在finally塊中return
try catch塊中永遠返回finally中return的值 錯誤 static boolean f finally 錯誤分析 在這個應用場景中,不要用return來退出finally語句塊,因為finally語句塊都會被執行到,這樣try程式塊中執行正常也會在finally中退出,不會再回到tr...