1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        工作10年后,再看String s = new String("xyz") 創(chuàng)建了幾個對象?

        共 1853字,需瀏覽 4分鐘

         ·

        2020-10-03 08:06

        這個問題相信每個學(xué)習(xí)java的同學(xué)都不陌生,作為一個經(jīng)典的面試題,到現(xiàn)在工作這么多年了我真是認(rèn)為挺操蛋的一個問題,在網(wǎng)上到現(xiàn)在你仍然可以看見很多討論這個問題的人,其中不乏工作很多年的人都有爭論,我認(rèn)為還是有必要來說一說這個問題的。

        ?

        從方法區(qū)說起

        常量池存在于方法區(qū),而方法區(qū)在jdk1.7版本前后改變比較大,所以還是先來說說方法區(qū)的演變。

        在jdk1.7版本之前,常量池存在于方法區(qū),方法區(qū)是堆的一個邏輯部分,他有一個名字叫做非堆。


        1.7版本把字符串常量池放到了堆中。


        而在1.8以后,則是移除了永久代,方法區(qū)概念保留,方法區(qū)的實現(xiàn)改為了元空間,常量池還是在堆中。


        為什么要說方法區(qū)的改變,只是為了文章接下來的內(nèi)容不會由于JDK的版本而產(chǎn)生分歧,接下來內(nèi)容都會以jdk1.8版本作為基礎(chǔ)來討論。


        String s = new String("xyz");

        先來一段代碼

        public?class?Test?{
        ????public?static?void?main(String[]?args)?{
        ????????String?s?=?"xyz";
        ????}
        }

        接著我們javac編譯代碼,然后用javap來反編譯,執(zhí)行javap -c Test


        從結(jié)果來看,ldc命令在常量池中創(chuàng)建了一個"xyz"的對象,然后把他推至操作數(shù)棧頂,然后astore保存到局部變量,return返回。

        接著看第二段面試題中的代碼

        public?class?Test?{
        ????public?static?void?main(String[]?args)?{
        ????????String?s?=?new?String("xyz");
        ????}
        }

        同樣反編譯分析


        很明顯,我們看到new 創(chuàng)建了一個String對象,同時ldc在常量池中創(chuàng)建了"xyz"字符串對象,之后invokespecial執(zhí)行構(gòu)造函數(shù),astore_1賦值,return返回。

        通過以上兩個例子,可以知道String s = new String("xyz"); 創(chuàng)建了2個對象,而有些答案說的3個對象,則是把引用s也算作一個對象。

        還有答案說xyz存在就創(chuàng)建了2個,不存在就創(chuàng)建了3個(包含引用s),再來測試一下。

        public?class?Test?{
        ????public?static?void?main(String[]?args)?{
        ????????String?s?=?"xyz";
        ????????String?s2?=?new?String("xyz");
        ????}
        }



        從這里,很明顯的發(fā)現(xiàn)這就是我們例子1和2的一個結(jié)合,但是注意兩次ldc后面的#2,#號代表著索引,說明第二次new String("xyz")的時候并沒有重新創(chuàng)建xyz對象。

        一些常見的指令助記符含義:

        1. nop, 什么都不做。

        2. aconst_null,將 null 推送至棧頂。

        3. iconst_i(變量數(shù)字),將 int 型 i 推送至棧頂。同理有l(wèi)const_0,fconst_0這種你應(yīng)該知道什么意思了

        4. ldc,將 int,float 或 String 型常量值從常量池中推送至棧頂。

        5. iload,將指定的 int 型局部變量推送至棧頂。

        6. istore,將棧頂 int 型數(shù)值存入指定局部變量。同理astore_i代表將棧頂引用型數(shù)值存入第i個局部變量。

        7. dup,復(fù)制棧頂數(shù)值并將復(fù)制值壓入棧頂。

        8. invokevirtual,調(diào)用實例方法。

        9. invokespecial,調(diào)用超類構(gòu)造方法,實例初始化方法,私有方法。

        10. invokestatic,調(diào)用靜態(tài)方法。

        11. invokeinterface,調(diào)用接口方法。

        12. invokedynamic,調(diào)用動態(tài)鏈接方法。

        13. new,創(chuàng)建一個對象,并將其引用值壓入棧頂。


        總結(jié)

        到底創(chuàng)建了幾個對象呢?

        1. 如果xyz不存在,引用算對象的話,那就是3個
        2. 如果xyz不存在,引用不算對象的話,那就是2個
        3. 如果xyz存在,引用算對象的話,那就是2個
        4. 如果xyz存在,引用不算對象的話,那就是1個
        當(dāng)然,我認(rèn)為引用肯定是不算對象的,最終答案應(yīng)該是1或者2個,這個面試題說實話不應(yīng)該出現(xiàn)在初級面試題里。

        有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)

        歡迎大家關(guān)注Java之道公眾號


        好文章,我在看??

        瀏覽 30
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            精品国产第一区二区三区的区别 | 美女激情影院 | 三级片视频网站 | 日韩国产专区 | 亚洲色图图片 | 日韩无码日韩有码 | 日韩在线视屏 | 刘亦菲全身脱得精光视频 | 草逼网视频 | 久久久人人人 |