先说结论:

在 Java 7 之后 Java 对String进行了优化改造
当未用 ; 结束并使用 + 拼接的语句速度不但不比 append() 慢,甚至还要略快一点。

 对于初学Java的人来说,在学习String的时候,肯定有无数个人和我们讲过,”尽量不要使用+拼接字符串,效率不好,应该使用append,你自己循环拼接个十万次自己瞧瞧就知道了“,然后像下面那样给我们演示了一下,用+和用StringBuilder的append拼接个十万次,输出一下各自消耗的时间,差距非常大,让我们立刻深信不疑,+拼接就是个垃圾,除了平时方便测试代码,否则都不要去用了,并且当有初学者使用+拼接时,也会毫不犹豫地去高谈阔论地教育一番。


public class Test {
public static void main(String[] args){
String str = "";
long start = System.currentTimeMillis();
for(int i=0; i<100000; i++)
str += "a";
long end = System.currentTimeMillis();
System.out.println(end - start);

StringBuilder sb = new StringBuilder();
start = System.currentTimeMillis();
for(int i=0; i<100000; i++)
sb.append("a");
str = sb.toString();
end = System.currentTimeMillis();
System.out.println(end - start);
}
}

上面的方框是+循环拼接,下面的方框是append循环拼接。
可以看到循环中+拼接会创建一个StringBuilder,除此之外和直接使用StringBuilder没有两样,但问题是每次循环都会new一个StringBuilder,也就是说效率就差在这里了。

(在刚学Java7的时候,我从别人那里得到一个很搞笑的解释,”+拼接底层实际上是使用了StringBuilder,所以效率很低,因此我们应该在任何时候都使用StringBuffer来拼接字符串“,噗,真不知道这种混乱的逻辑是怎么产生的,StringBuffer是线程安全的怎么可能比StringBuilder效率高,233333)

对于此处的str = str + “a”,编译器会处理为new StringBuilder().append(str).append(“a”),不管一次性+几个字符串,只要+拼接全部在一条语句中,就只会new一次,
循环中+拼接被断成了十万条语句,那自然就会new十万次,当然就慢得多了。

可以看到,对于有String类型变量参与的情况(String变量+”字面量” 或者 String变量+String变量),只要+拼接没有断,那就会一直调用append,一旦另起一条语句,马上就会new一个StringBuilder。从结果来看,字符串字面量的拼接是不会使用new的。

Java中+拼接字符串并不是人们口中所说的那样臭名昭著,人们口中所说的效率低下指的是在循环中的+拼接,只是不知道从哪天开始完全变了味。如果你能保证在一条语句中把字符串或者字符串变量全部拼接完而不断开,那+拼接根本没有任何缺点,编译器还会有一些优化,如果拼接的全是字符串字面量,那效果更好,它们直接就变成了一个完整的字符串。并且+书写简洁方便,可读性强。直接用StringBuilder的append也没有问题,只是不要append()和+混合使用。