很久沒維護《吊打面試官》系列了,今天再來一篇,此次真的要吊打了,哈哈!(看往期吊打系列請在後臺回覆:吊打,我會陸續更新……)java
咱們作 Java 程序員以來,無論是工做當中,仍是面試過程當中,都知道:字符串拼接不能用 String,要用 StringBuilder
或者是 StringBuffer
,以致於它們都被濫用了。程序員
StringBuilder、StringBuffer 簡稱:SB,下文統一用 SB
代替。面試
SB
它們都是可變的字符串,它們之間的區別也是 Java 初中級面試戰場上出現概率十分高的一道題,上場率沒有 90% 也有 80% 吧。sql
這兩個的具體區別請看這篇文章:StringBuffer 和 StringBuilder 的 3 個區別。微信
咱們反過來想下,String真的是不可變的麼?不必定,看下這篇:Java 中的 String 真的是不可變的嗎?app
固然,本文不是討論字符串可變與不可變的問題,而是討論:字符串拼接必定要用 SB
嗎?爲何不能用 +
?能不能用 +
?何時能夠用 +
?性能
爲何不能用 + 號拼接字符串?我不服,接下來我要吊打面試官!優化
+
經過多個表達式完成一個字符串拼接操做。ui
private void test1() { String www = "www."; String str = www; str += "javastack."; str += "com"; }
字節碼以下:this
// 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
的時候了。
也就是說,在一個表達式中完成字符串拼接是能夠用 +
號完成的,由於編譯器已經作了優化。
你只須要記住這兩點:
一、在循環和多個表達式中不能 +
,頻繁建立 SB
性能影響;
二、在單個表達式中能夠用 +
,編譯器直接作了優化;
老鐵們,都搞清楚了?
這個觀點有沒有被誤解好久?
下次面試,把這篇內容亮出來,吊打面試官,沒問題的。
有收穫的朋友必定要點個在看,這樣我寫原創更帶勁了,謝了,老鐵們。
關注Java技術棧微信公衆號,棧長將繼續分享好玩的 Java 技術,公衆號第一時間推送,在公衆號後臺回覆:Java,能夠獲取歷史 Java 教程,都是乾貨。