日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java.lang.String 的 + 号操作,这个谜终于要解开了!

發(fā)布時間:2025/3/21 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java.lang.String 的 + 号操作,这个谜终于要解开了! 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

作者:丶Pz ?
來源:https://www.cnblogs.com/panzi/p/11956782.html

在之前的面試經歷中,對于String的考察還是挺頻繁的,大致考察以下幾個知識點:

  • String 常量池

  • new String()

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

  • native 方法 String.intern()

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

String?str3?=?"what"; String?str4?=?str3?+?"?a?nice?day"; //運行時,?+?相當于 new,所以堆中會有?"what a nice day"對象,常量池中會有"what"," a nice day"兩個對象,而不會有?"what a nice day"對象。 //這句話大佬們看看對不對啊,我怎么感覺不對啊 //常量池不會有"what a nice day"?對象嗎?

看完這個問題,說實話我也是有點懵的,我只是知道 "what a nice day"不會在常量池,但是不知道具體的原因,后來群里的同學說 + 號是調用了 StringBuffer 的append 方法。我去證實了,發(fā)現(xiàn)確實調用了 append 方法,但是當時沒有 調用toString()方法,我很疑惑。(最后經過證實,是StringBuilder的append 方法,不是StringBuffer)。

代碼驗證

public?static?void?main(String[]?args)?{//#1String?str1?=?"what";//#2String?str2?=?str1?+?"?a?nice?day";//#3System.out.println("what?a?nice?day".equals(str2));//#4System.out.println("what?a?nice?day"?==?str2); }

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

  • str1 存放位置?

  • str2 存放位置?

  • 結果是 true 還是 false?

  • 結果是 true 還是 false?

  • "what a nice day" 存放在哪個位置呢?

  • 解答分析(基于JDK1.8)

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

    localhost:test?didi$?javap?-verbose?-p?Main.class Classfile?/develop/project/string-test/out/production/classes/com/fanpan26/string/test/Main.classLast?modified?2019-11-29;?size?972?bytesMD5?checksum?1d1f1a23bfe85c2f88d2f767e8aac314Compiled?from?"Main.java" public?class?com.fanpan26.string.test.Mainminor?version:?0major?version:?52flags:?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:?()Vflags:?ACC_PUBLICCode:stack=1,?locals=1,?args_size=10:?aload_01:?invokespecial?#1??????????????????//?Method?java/lang/Object."<init>":()V4:?returnLineNumberTable:line?6:?0LocalVariableTable:Start??Length??Slot??Name???Signature0???????5?????0??this???Lcom/fanpan26/string/test/Main;public?static?void?main(java.lang.String[]);descriptor:?([Ljava/lang/String;)Vflags:?ACC_PUBLIC,?ACC_STATICCode:stack=3,?locals=3,?args_size=10:?ldc???????????#2??????????????????//?String?what2:?astore_13:?new???????????#3??????????????????//?class?java/lang/StringBuilder6:?dup7:?invokespecial?#4??????????????????//?Method?java/lang/StringBuilder."<init>":()V10:?aload_111:?invokevirtual?#5??????????????????//?Method?java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;14:?ldc???????????#6??????????????????//?String??a?nice?day16:?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_223:?getstatic?????#8??????????????????//?Field?java/lang/System.out:Ljava/io/PrintStream;26:?ldc???????????#9??????????????????//?String?what?a?nice?day28:?aload_229:?invokevirtual?#10?????????????????//?Method?java/lang/String.equals:(Ljava/lang/Object;)Z32:?invokevirtual?#11?????????????????//?Method?java/io/PrintStream.println:(Z)V35:?getstatic?????#8??????????????????//?Field?java/lang/System.out:Ljava/io/PrintStream;38:?ldc???????????#9??????????????????//?String?what?a?nice?day40:?aload_241:?if_acmpne?????4844:?iconst_145:?goto??????????4948:?iconst_049:?invokevirtual?#11?????????????????//?Method?java/io/PrintStream.println:(Z)V52:?returnLineNumberTable:line?9:?0line?11:?3line?13:?23line?15:?35line?16:?52LocalVariableTable:Start??Length??Slot??Name???Signature0??????53?????0??args???[Ljava/lang/String;3??????50?????1??str1???Ljava/lang/String;23??????30?????2??str2???Ljava/lang/String;StackMapTable:?number_of_entries?=?2frame_type?=?255?/*?full_frame?*/offset_delta?=?48locals?=?[?class?"[Ljava/lang/String;",?class?java/lang/String,?class?java/lang/String?]stack?=?[?class?java/io/PrintStream?]frame_type?=?255?/*?full_frame?*/offset_delta?=?0locals?=?[?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兩個問題。

    • str1 是存放在常量池的

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

    下面我們看一下 + 操作做了什么事情,可以在Code中看到,該操作調用了 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

    所以說其實 str1 + " a nice day" 就相當于 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();

    而StringBuilder 的toString 方法如下:

    @Override public?String?toString()?{//?所以說 str2 其實是一個 new String,是不在常量池里面的。return?new?String(value,?0,?count); }

    總結

    通過類的字節(jié)碼可以查看底層具體用什么方式實現(xiàn),所以說雖然看似一個簡單的String問題,其實往深處挖掘還是考察了對生成的字節(jié)碼的理解。還有,遇到一個問題,不能死記答案,有些人告訴你,+ 操作就是 new 對象,但是具體到底是不是或者為什么是有沒有思考過呢?上文中如有錯誤,歡迎指出。

    試一試

    /***?以下程序輸出的結果是什么?*?*/ 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); } /***?以下程序輸出的結果是什么?*?*/ 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); } /***?以下程序輸出的結果是什么?*?*/ 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()); }

    ?

    總結

    以上是生活随笔為你收集整理的java.lang.String 的 + 号操作,这个谜终于要解开了!的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。