不能用 + 拼接字符串? 这次我要吊打面试官!
好久沒維護《吊打面試官》系列了,今天再來一篇,這次真的要吊打了,哈哈!(看往期吊打系列請在后臺回復:吊打,我會陸續更新……)
我們做 Java 程序員以來,不管是工作當中,還是面試過程中,都知道:字符串拼接不能用 String,要用?StringBuilder?或者是?StringBuffer,以至于它們都被濫用了。
StringBuilder、StringBuffer 簡稱:SB,下文統一用?SB?代替。
SB它們都是可變的字符串,它們之間的區別也是 Java 初中級面試戰場上出現幾率十分高的一道題,上場率沒有 90% 也有 80% 吧。
這兩個的具體區別請看這篇文章:StringBuffer 和 StringBuilder 的 3 個區別。
我們反過來想下,String真的是不可變的么?不一定,看下這篇:Java 中的 String 真的是不可變的嗎?
當然,本文不是討論字符串可變與不可變的問題,而是討論:字符串拼接一定要用?SB?嗎?為什么不能用?+??能不能用?+??什么時候可以用?+??
為什么不能用 + 號拼接字符串?我不服,接下來我要吊打面試官!
什么時候不能用 `+`
通過多個表達式完成一個字符串拼接操作。
private?void?test1()?{String?www?=?"www.";String?str?=?www;str?+=?"javastack.";str?+=?"com"; }字節碼如下:
//?access?flags?0xA private?static?test2()V L0 LINENUMBER?14?L0 LDC?"www." ASTORE?0 L1 LINENUMBER?15?L1 ALOAD?0 ASTORE?1 L2 LINENUMBER?16?L2 NEW?java/lang/StringBuilder DUP INVOKESPECIAL?java/lang/StringBuilder.<init>?()V ALOAD?1 INVOKEVIRTUAL?java/lang/StringBuilder.append?(Ljava/lang/String;)Ljava/lang/StringBuilder; LDC?"javastack." INVOKEVIRTUAL?java/lang/StringBuilder.append?(Ljava/lang/String;)Ljava/lang/StringBuilder; INVOKEVIRTUAL?java/lang/StringBuilder.toString?()Ljava/lang/String; ASTORE?1 L3 LINENUMBER?17?L3 NEW?java/lang/StringBuilder DUP INVOKESPECIAL?java/lang/StringBuilder.<init>?()V ALOAD?1 INVOKEVIRTUAL?java/lang/StringBuilder.append?(Ljava/lang/String;)Ljava/lang/StringBuilder; LDC?"com" INVOKEVIRTUAL?java/lang/StringBuilder.append?(Ljava/lang/String;)Ljava/lang/StringBuilder; INVOKEVIRTUAL?java/lang/StringBuilder.toString?()Ljava/lang/String; ASTORE?1 L4 LINENUMBER?18?L4 RETURN L5 LOCALVARIABLE?www?Ljava/lang/String;?L1?L5?0 LOCALVARIABLE?str?Ljava/lang/String;?L2?L5?1 MAXSTACK?=?2 MAXLOCALS?=?2不會查看字節碼的,看這里:3種騷操作,教你查看 Java 字節碼,看這一篇就會了。
觀察下,NEW java/lang/StringBuilder?出現了兩次,是因為我們在代碼中拼接了兩次,也就是說每一次拼接操作都會創建一次?StringBuilder。
如果我們是在一個循環中進行字符串拼接,那是不是一次拼接就要創建一個?StringBuilder?
wtf……這哪能接受!頻繁創建對象是有性能開銷的,這也是為什么我們常說的字符串不能用?+?拼接,而要用那兩個?SB??拼接了。
?
什么時候可以用 `+`
直接將三個字面量的字符串拼接成一個字符串。
private?static?void?test2()?{String?str?=?"www."?+?"javastack."?+?"com"; }字節碼如下:
//?access?flags?0x2 private?test2()V L0 LINENUMBER?13?L0 LDC?"www.javastack.com" ASTORE?1 L1 LINENUMBER?14?L1 RETURN L2 LOCALVARIABLE?this?Lcom/test/jdk/TestSB;?L0?L2?0 LOCALVARIABLE?str?Ljava/lang/String;?L1?L2?1 MAXSTACK?=?1 MAXLOCALS?=?2從字節碼看出,沒有任何創建?StringBuilder?的指令,直接從常量池進行取出一個完整的字符串:www.javastack.com。很明顯,這是 Java 編譯器對代碼進行了優化。
所以,通過這個示例告訴你,在這種情況下是可以用?+?號進行字符串拼接的。
這個示例可以演變成我們實際工作當中的某個 SQL 語句拼接的案例,如:
String?sql?=?"select?name,?sex,?age,?address"+?"from?t_user"+?"where?age?>?18";別說這樣不行,這樣是行的。
但你要是換成這樣就不行了:
String?sql?=?"select?name,?sex,?age,?address"; sql?+=?"from?t_user"; sql?+=?"where?age?>?18";這樣又回到創建多個?StringBuilder?的時候了。
也就是說,在一個表達式中完成字符串拼接是可以用?+?號完成的,因為編譯器已經做了優化。
小結一下
你只需要記住這兩點:
1、在循環和多個表達式中不能?+,頻繁創建?SB?性能影響;
2、在單個表達式中可以用?+,編譯器直接做了優化;
老鐵們,都搞清楚了?
這個觀點有沒有被誤解很久?
下次面試,把這篇內容亮出來,吊打面試官,沒問題的。
有收獲的朋友一定要點個在看,這樣我寫原創更帶勁了,謝了,老鐵們。
總結
以上是生活随笔為你收集整理的不能用 + 拼接字符串? 这次我要吊打面试官!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: StringBuffer 和 Strin
- 下一篇: 女儿问了我一个问题:什么是抽象?