国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

面試題思考:try 代碼塊中含 return 語句時,代碼執行順序

chunquedong / 995人閱讀

摘要:刷面試題偶然看到這類問題中含有時的執行順序,覺得挺有意思于是小小的研究了一下,希望經過我添油加醋天馬行空之后,能給你帶來一定的幫助原題里有一個語句,那么緊跟在這個后的里的代碼會不會被執行什么時候被執行在前還是后乍一看題目很簡單嘛,規范都說了

刷java面試題偶然看到這類問題(try/finally中含有return時的執行順序),覺得挺有意思于是小小的研究了一下,希望經過我添油加醋天馬行空之后,能給你帶來一定的幫助

原題

try {} 里有一個return語句,那么緊跟在這個try后的finally {}里的代碼會不會被執行?什么時候被執行?在return前還是后?

乍一看題目很簡單嘛,java規范都說了,finally會在try代碼塊的return之前執行,你這文章寫得沒意義,不看了

你等等!(拿起我身邊的五尺砍刀)

神奇栗子

看完這個栗子,你在想想執行順序到底是怎樣的

栗子代碼
    public static void main(String[] args) {
        int result = test();
        System.out.println(result);
    }

    public static int test() {
        int t = 0;
        try {
            return t;
        } finally {
            ++t;
        }
    }
分析一下

test()方法內,在try中return了t,那么在main方法中test()函數的返回值應該是t=0,即控制臺輸出0

但是因為有finally的存在,而finally中對t進行了自增運算,并且finally會在try中的return語句之前執行,所以正確的情況是控制臺輸出1

所以你最終確定的答案是:控制臺輸出1

然而事實并非如此,將程序跑起來之后,得到的結果是:

輸出0
將栗子跑起來親眼看一下吧~

得到這個結果你也許要爆炸了,啥?java規范說的都是錯的?!

不用急,到我給sun洗地的時間了

洗地時間

在洗地之前,你很有必要先理解java中的值傳遞,如果你已經了解該內容可略過下面這一個小節點

java中的值傳遞

由于這只是本文內容引申出去的知識點,不過多贅述,隨便嘮兩句,能借此明白則好,不明白希望借助搜索引擎明白一下!

在java的方法調用中,時常需要傳遞參數,那么傳遞的參數是將之前的變量直接傳遞給方法內了嗎?

顯然不是的,調用方法傳遞參數的時候,傳遞的只是原變量的一個副本(復制體),換句話說就是,將變量的值傳遞給了方法體,而并沒有真正的將變量傳遞進去。

看個栗子:

    public static void main(String[] args) {
        int t = 0;
        test(t);
        System.out.println(t);
    }

    public static int test(int a) {
        a = 111;
    }

正確輸出是0,因為test()方法內拿到的a,只是t的一個副本(復制體)而并不直接是t,test()內改變了a的值,并不影響t的值

以上是對于基本數據類型,如果對于對象呢?

如果參數是對象,那么傳遞的是對象的引用副本(復制體),這也就是為什么在方法體內對對象進行修改,會真正的改變對象。因為方法體外的引用和方法體內的引用指向的是堆內存中的同一個對象,傳遞的是對象的引用

如果這里還不能理解值傳遞,建議先理解一下這一個概念再繼續往下看

真的開始分析了

為了你看著方便,栗子代碼再來一份:(我真的不是為了湊字數)

    public static void main(String[] args) {
        int result = test();
        System.out.println(result);
    }

    public static int test() {
        int t = 0;
        try {
            return t;
        } finally {
            ++t;
        }
    }

當代碼執行到return t;時,并不是直接將t返回了出去,而是將t保留了起來(因為還有一個finally語句塊沒有執行!)

并且這個保留,就是值傳遞性質的一個保留,也就是保留的是t的一個副本(復制體),我這里先叫他tt吧(不是套套!!)

接下來執行finally語句塊,finally中將t做了自增運算,t的確變成了1,但是這并沒有影響t的復制體tt的值!保留起來的tt值還是0!

這個時候執行完了finally,正式將保留起來的tt返回出去,于是,整個函數的返回結果就是0

這個t的副本(復制體)保留的地方是哪兒呢?我查了半天,有個應該靠譜的說法,保留在函數棧中,但具體保留的區域叫什么,我也不知道,還請知情大佬指教一下!

上圖或許直觀一點?


叫我一聲靈魂畫師我可敢答應!

那么如果,這個t是一個對象呢?按照前面說的值傳遞的問題,如果t是一個對象,在finally中對t進行修改,那么最終返回出去的t所顯示出來的數據,應該是經過修改的。

寫一個Person類來檢驗一下吧

public class Test {

    public static void main(String[] args) {
        Person result = test();
        System.out.println(result.age);
    }

    public static Person test() {
        Person t = new Person();
        t.age = 0;
        try {
            return t;
        } finally {
            t.age++;
            
        }
    }

}

class Person {
    int age;
}

這段代碼輸出的是1,因為Person是一個類,t是一個對象的引用,對象實例保存在堆內存中,t的副本tt也是一個對象的引用,t和tt都指向堆內存中的對象實例,那么不論修改誰,實際上對象實例都被修改了!

看完我這一通胡說八道,你應該了解了整個執行流程咯?

那么繼續開一個引申

又一個小栗子

如果在finally中也有一個return,會發生什么?

    public static void main(String[] args) {
        int result = test();
        System.out.println(result);
    }

    public static int test() {
        int t = 0;
        try {
            return t;
        } finally {
            ++t;
            return t;
        }
    }

最終輸出的結果是1

就是說,如果try中有return而finally中也有return,那么后者將會讓前者失效!

理解

=> try中將t保留了一份副本用于返回出去,到了finally中,又有一個return語句,這時候又要創建一個用于返回的副本,那這個時候就有兩個副本了,到底返回誰呢?取后者!

總結

這一個面試題,看似簡單,卻暗藏殺機啊!

可是說了這么多,結果就是finally在return之后執行嗎?

非也,你沒看見return沒有真正的執行完就開始執行finally嗎?并且是先執行完了finally,才執行完return,這也就很好理解java規范中的finally在return之前執行了。

不過,按如上情況,這句話應該變成這樣:finally比return先執行完畢。是不是就更容易理解了呢?

也就是說,return先被執行了,執行return的時候發現有finally,于是不能那么快執行完畢return,先去執行finally,等finally執行完畢之后,return才能執行完畢。

全文下來,真是用我的三寸不爛之舌經過滔滔不絕的輸出連綿不絕的蠱惑打開了你的新世界大門啊

結語

更多內容歡迎訪問我的主頁我的博客
如果我的文章確實有幫助到你,請不要忘了點一下文末的"?"讓他變成"?"
作為一直雛雞難免很多地方理解不到位,文中若有錯誤請直(bu)接(yao)指(ma)出(wo)
寫作不易!

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/69950.html

相關文章

  • java 基礎 - 收藏集 - 掘金

    摘要:基礎知識復習后端掘金的作用表示靜態修飾符,使用修飾的變量,在中分配內存后一直存在,直到程序退出才釋放空間。將對象編碼為字節流稱之為序列化,反之將字節流重建成對象稱之為反序列化。 Java 學習過程|完整思維導圖 - 后端 - 掘金JVM 1. 內存模型( 內存分為幾部分? 堆溢出、棧溢出原因及實例?線上如何排查?) 2. 類加載機制 3. 垃圾回收 Java基礎 什么是接口?什么是抽象...

    makeFoxPlay 評論0 收藏0
  • 校招一次次被刷,已經不想找工作了,我該怎么辦?

    摘要:前兩天有粉絲聯系我,說他軟件工程專業,大廠校招屢次被刷,有一個已經到了三面,還是被刷了,感覺很絕望,不想找工作了。講一講協議的三次握手和四次揮手流程。什么是檢查異常,不受檢查異常,運行時異常并分別舉例說明。 前兩天有粉絲聯系我,說他軟件工程專業,大廠校招屢次被刷,有一個已經到了三面,還是被刷...

    doodlewind 評論0 收藏0
  • 異常機制詳解

    摘要:當運行時系統遍歷調用棧而未找到合適的異常處理器,則運行時系統終止。不可查異常編譯器不要求強制處置的異常包括運行時異常與其子類和錯誤。 目錄介紹 1.什么是異常 2.異常 2.1 異常的概述和分類【了解】 2.2 JVM默認是如何處理異常的【理解】 2.3 異常處理的兩種方式【理解】 2.4 try...catch的方式處理異常【掌握】 2.5 編譯期異常和運行期異常的區別【理解】...

    wanghui 評論0 收藏0
  • 新鮮出爐的8月前端面試

    摘要:前言最近參加了幾場面試,積累了一些高頻面試題,我把面試題分為兩類,一種是基礎試題主要考察前端技基礎是否扎實,是否能夠將前端知識體系串聯。 前言 最近參加了幾場面試,積累了一些高頻面試題,我把面試題分為兩類,一種是基礎試題: 主要考察前端技基礎是否扎實,是否能夠將前端知識體系串聯。一種是開放式問題: 考察業務積累,是否有自己的思考,思考問題的方式,這類問題沒有標準答案。 基礎題 題目的答...

    qingshanli1988 評論0 收藏0

發表評論

0條評論

chunquedong

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<