免费在线a视频-免费在线观看a视频-免费在线观看大片影视大全-免费在线观看的视频-色播丁香-色播基地

java.lang.String 的 + 號(hào)操作到底做了什么?

:2020年02月11日 腳本之家
分享到:

在之前的面試經(jīng)歷中,對(duì)于String的考察還是挺頻繁的,大致考察以下幾個(gè)知識(shí)點(diǎn):String 常量池new String()== 和 equals 的區(qū)別native 方法 String.intern()雖然面試中大體答對(duì)了,但是今天早上微信群里的...

在之前的面試經(jīng)歷中,對(duì)于String的考察還是挺頻繁的,大致考察以下幾個(gè)知識(shí)點(diǎn):

  • String 常量池

  • new String()

  • == 和 equals 的區(qū)別

  • native 方法 String.intern()

雖然面試中大體答對(duì)了,但是今天早上微信群里的一個(gè)問題我卻答不上來,這個(gè)問題是這樣的:

String str3 = "what";

String str4 = str3 + " a nice day";

//運(yùn)行時(shí), + 相當(dāng)于 new,所以堆中會(huì)有 "what a nice day"對(duì)象,常量池中會(huì)有"what"," a nice day"兩個(gè)對(duì)象,而不會(huì)有 "what a nice day"對(duì)象。

//這句話大佬們看看對(duì)不對(duì)啊,我怎么感覺不對(duì)啊

//常量池不會(huì)有"what a nice day" 對(duì)象嗎?

看完這個(gè)問題,說實(shí)話我也是有點(diǎn)懵的,我只是知道 "what a nice day"不會(huì)在常量池,但是不知道具體的原因,后來群里的同學(xué)說 + 號(hào)是調(diào)用了 StringBuffer 的append 方法。

我去證實(shí)了,發(fā)現(xiàn)確實(shí)調(diào)用了 append 方法,但是當(dāng)時(shí)沒有 調(diào)用toString()方法,我很疑惑。(最后經(jīng)過證實(shí),是StringBuilder的append 方法,不是StringBuffer)。

代碼驗(yàn)證

public static void main(String[] args) {

    //#1

    String str1 = "what";

    //#2

    String str2 = str1 + " a nice day";

    //#3

    System.out.println("what a nice day".equals(str2));

    //#4

    System.out.println("what a nice day" == str2);

}

現(xiàn)在有以下幾個(gè)問題,小伙伴們看看是否能答出來,即使答出來了,你知道為什么嗎?

  1. str1 存放位置?

  2. str2 存放位置?

  3. 結(jié)果是 true 還是 false?

  4. 結(jié)果是 true 還是 false?

  5. "what a nice day" 存放在哪個(gè)位置呢?

解答分析(基于JDK1.8)

下面也不靠猜,我們直接查看生成的字節(jié)碼:

localhost:test didi$ javap -verbose -p Main.class

Classfile /develop/project/string-test/out/production/classes/com/fanpan26/string/test/Main.class

  Last modified 2019-11-29; size 972 bytes

  MD5 checksum 1d1f1a23bfe85c2f88d2f767e8aac314

  Compiled from "Main.java"

public class com.fanpan26.string.test.Main

  minor version: 0

  major version: 52

  flags: ACC_PUBLIC, ACC_SUPER

Constant pool:

   #1 = Methodref          #13.#34        // java/lang/Object."<init>":()V

   #2 = String             #35            // what

   #3 = Class              #36            // java/lang/StringBuilder

   #4 = Methodref          #3.#34         // java/lang/StringBuilder."<init>":()V

   #5 = Methodref          #3.#37         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

   #6 = String             #38            //  a nice day

   #7 = Methodref          #3.#39         // java/lang/StringBuilder.toString:()Ljava/lang/String;

   #8 = Fieldref           #40.#41        // java/lang/System.out:Ljava/io/PrintStream;

   #9 = String             #42            // what a nice day

  #10 = Methodref          #43.#44        // java/lang/String.equals:(Ljava/lang/Object;)Z

  #11 = Methodref          #45.#46        // java/io/PrintStream.println:(Z)V

  #12 = Class              #47            // com/fanpan26/string/test/Main

  #13 = Class              #48            // java/lang/Object

  #14 = Utf8               <init>

  #15 = Utf8               ()V

  #16 = Utf8               Code

  #17 = Utf8               LineNumberTable

  #18 = Utf8               LocalVariableTable

  #19 = Utf8               this

  #20 = Utf8               Lcom/fanpan26/string/test/Main;

  #21 = Utf8               main

  #22 = Utf8               ([Ljava/lang/String;)V

  #23 = Utf8               args

  #24 = Utf8               [Ljava/lang/String;

  #25 = Utf8               str1

  #26 = Utf8               Ljava/lang/String;

  #27 = Utf8               str2

  #28 = Utf8               StackMapTable

  #29 = Class              #24            // "[Ljava/lang/String;"

  #30 = Class              #49            // java/lang/String

  #31 = Class              #50            // java/io/PrintStream

  #32 = Utf8               SourceFile

  #33 = Utf8               Main.java

  #34 = NameAndType        #14:#15        // "<init>":()V

  #35 = Utf8               what

  #36 = Utf8               java/lang/StringBuilder

  #37 = NameAndType        #51:#52        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

  #38 = Utf8                a nice day

  #39 = NameAndType        #53:#54        // toString:()Ljava/lang/String;

  #40 = Class              #55            // java/lang/System

  #41 = NameAndType        #56:#57        // out:Ljava/io/PrintStream;

  #42 = Utf8               what a nice day

  #43 = Class              #49            // java/lang/String

  #44 = NameAndType        #58:#59        // equals:(Ljava/lang/Object;)Z

  #45 = Class              #50            // java/io/PrintStream

  #46 = NameAndType        #60:#61        // println:(Z)V

  #47 = Utf8               com/fanpan26/string/test/Main

  #48 = Utf8               java/lang/Object

  #49 = Utf8               java/lang/String

  #50 = Utf8               java/io/PrintStream

  #51 = Utf8               append

  #52 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;

  #53 = Utf8               toString

  #54 = Utf8               ()Ljava/lang/String;

  #55 = Utf8               java/lang/System

  #56 = Utf8               out

  #57 = Utf8               Ljava/io/PrintStream;

  #58 = Utf8               equals

  #59 = Utf8               (Ljava/lang/Object;)Z

  #60 = Utf8               println

  #61 = Utf8               (Z)V

{

  public com.fanpan26.string.test.Main();

    descriptor: ()V

    flags: ACC_PUBLIC

    Code:

      stack=1, locals=1, args_size=1

         0: aload_0

         1: invokespecial #1                  // Method java/lang/Object."<init>":()V

         4: return

      LineNumberTable:

        line 6: 0

      LocalVariableTable:

        Start  Length  Slot  Name   Signature

            0       5     0  this   Lcom/fanpan26/string/test/Main;

  public static void main(java.lang.String[]);

    descriptor: ([Ljava/lang/String;)V

    flags: ACC_PUBLIC, ACC_STATIC

    Code:

      stack=3, locals=3, args_size=1

         0: ldc           #2                  // String what

         2: astore_1

         3: new           #3                  // class java/lang/StringBuilder

         6: dup

         7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V

        10: aload_1

        11: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

        14: ldc           #6                  // String  a nice day

        16: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

        19: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;

        22: astore_2

        23: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;

        26: ldc           #9                  // String what a nice day

        28: aload_2

        29: invokevirtual #10                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z

        32: invokevirtual #11                 // Method java/io/PrintStream.println:(Z)V

        35: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;

        38: ldc           #9                  // String what a nice day

        40: aload_2

        41: if_acmpne     48

        44: iconst_1

        45: goto          49

        48: iconst_0

        49: invokevirtual #11                 // Method java/io/PrintStream.println:(Z)V

        52: return

      LineNumberTable:

        line 9: 0

        line 11: 3

        line 13: 23

        line 15: 35

        line 16: 52

      LocalVariableTable:

        Start  Length  Slot  Name   Signature

            0      53     0  args   [Ljava/lang/String;

            3      50     1  str1   Ljava/lang/String;

           23      30     2  str2   Ljava/lang/String;

      StackMapTable: number_of_entries = 2

        frame_type = 255 /* full_frame */

          offset_delta = 48

          locals = [ class "[Ljava/lang/String;", class java/lang/String, class java/lang/String ]

          stack = [ class java/io/PrintStream ]

        frame_type = 255 /* full_frame */

          offset_delta = 0

          locals = [ class "[Ljava/lang/String;", class java/lang/String, class java/lang/String ]

          stack = [ class java/io/PrintStream, int ]

}

SourceFile: "Main.java"

從Constant pool: 中的信息可以看到,#2 、#6、#9 可以解答上文中的1,5兩個(gè)問題。

  • str1 是存放在常量池的

  • "what a nice day" (非str2)也是存放在常量池的

下面我們看一下 + 操作做了什么事情,可以在Code中看到,該操作調(diào)用了 StringBuilder.append 方法

11: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

14: ldc           #6                  // String  a nice day

16: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

19: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;

那么到這里一切都答案都出來了

  • str2 是存放在堆中

  • equals 為 true

  • == 為 false

所以說其實(shí) str1 + " a nice day" 就相當(dāng)于 new StringBuilder().append(str1).append(" a nice day");

//這兩種寫法生成的字節(jié)碼是一樣的。

//String str2 = str1 + " a nice day";

String str2 = new StringBuilder().append(str1).append(" a nice day").toString();

StringBuffer的toString 方法如下:

@Override

public String toString() {

    // 所以說 str2 其實(shí)是一個(gè) new String,是不在常量池里面的。

    return new String(value, 0, count);

}

總結(jié)

通過類的字節(jié)碼可以查看底層具體用什么方式實(shí)現(xiàn),所以說雖然看似一個(gè)簡(jiǎn)單的String問題,其實(shí)往深處挖掘還是考察了對(duì)生成的字節(jié)碼的理解。

還有,遇到一個(gè)問題,不能死記答案,有些人告訴你,+ 操作就是 new 對(duì)象,但是具體到底是不是或者為什么是有沒有思考過呢?上文中如有錯(cuò)誤,歡迎指出。

試一試

/**

 * 以下程序輸出的結(jié)果是什么?

 * */

public static void main(String[] args) {

    String str1 = "what";

    String str2 = str1 + " a nice day";

    System.out.println("what a nice day".equals(str2));

    System.out.println("what a nice day" == str2);

}

/**

 * 以下程序輸出的結(jié)果是什么?

 * */

public static void main(String[] args) {

    String str1 = "what a nice day";

    String str2 = new String("what a nice day");

    System.out.println(str1.equals(str2));

    System.out.println(str1 == str2);

}

/**

 * 以下程序輸出的結(jié)果是什么?

 * */

public static void main(String[] args) {

    String str1 = "what";

    String str2 = str1.concat(" a nice day");

    System.out.println("what a nice day".equals(str2));

    System.out.println("what a nice day" == str2);

    System.out.println("what a nice day"==str2.intern());

}

- END -

[我要糾錯(cuò)]
[ 編輯:王振袢 &發(fā)表于江蘇 ]
關(guān)鍵詞: 之前 面試 經(jīng)歷 對(duì)于 String

來源:本文內(nèi)容搜集或轉(zhuǎn)自各大網(wǎng)絡(luò)平臺(tái),并已注明來源、出處,如果轉(zhuǎn)載侵犯您的版權(quán)或非授權(quán)發(fā)布,請(qǐng)聯(lián)系小編,我們會(huì)及時(shí)審核處理。
聲明:江蘇教育黃頁對(duì)文中觀點(diǎn)保持中立,對(duì)所包含內(nèi)容的準(zhǔn)確性、可靠性或者完整性不提供任何明示或暗示的保證,不對(duì)文章觀點(diǎn)負(fù)責(zé),僅作分享之用,文章版權(quán)及插圖屬于原作者。

點(diǎn)個(gè)贊
0
踩一腳
0

您在閱讀:java.lang.String 的 + 號(hào)操作到底做了什么?

Copyright©2013-2025 ?JSedu114 All Rights Reserved. 江蘇教育信息綜合發(fā)布查詢平臺(tái)保留所有權(quán)利

蘇公網(wǎng)安備32010402000125 蘇ICP備14051488號(hào)-3技術(shù)支持:南京博盛藍(lán)睿網(wǎng)絡(luò)科技有限公司

南京思必達(dá)教育科技有限公司版權(quán)所有   百度統(tǒng)計(jì)

主站蜘蛛池模板: 亚洲精品亚洲人成在线观看麻豆 | 免费一级欧美在线观看视频片 | 99精品视频在线观看免费播放 | 久久精品国产一区二区三区不卡 | 黄色大片视频在线观看 | 91精品导航在线观看 | 国产成人精品日本亚洲专区6 | 一级特黄aaa大片在线观看视频 | 日韩欧美一区二区三区在线观看 | 手机看片国产欧美日韩高清 | 免费一级夫妻a | 深夜免费看片 | 在线精品国产导航 | 我要看黄色毛片 | 日b视频免费 | 综合五月天堂 | 三级福利| 国产日韩视频在线观看 | 午夜影院免费入口 | 麻豆传煤一区免费入 | 99久在线| 日韩午夜高清福利片在线观看 | 国产乱码精品一区二区三区网页版 | 国产尤物二区三区在线观看 | 国产免费一级高清淫曰本片 | 一级毛片免费在线播放 | 成人男女网18免费0 成人男女网18免费91 | 成年美女黄网站色大片免费看 | 免费观看成人毛片 | 26uuu欧美视频在线观看 | 黄色大片视频网站 | 天天干夜夜爽天天操夜夜爽视频 | 日产精品一二三四区国产 | 免费午夜在线视频 | 国产精品xxxxbbbb18 | 97人人艹| 免费人成大片在线观看播放 | 欧美色图第二页 | 欧美日韩一区二区不卡 | 欧美区在线 | 免费日批 |
最熱文章
最新文章
  • 阿里云上云鉅惠,云產(chǎn)品享最低成本,有需要聯(lián)系,
  • 卡爾蔡司鏡片優(yōu)惠店,鏡片價(jià)格低
  • 蘋果原裝手機(jī)殼