很久没维护《吊打面试官》系列了,今天再来一篇,此次真的要吊打了,哈哈!(看往期吊打系列请在后台回复:吊打,我会陆续更新……)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 教程,都是干货。