前言:该问题是老生常谈,查看了很多博客都没有得到自己想要的。因此综合查看《Thinking in java》及《深入理解java虚拟机》再结合自己的理解,总结该篇文章。
1. String
String是不可变的,每次修改String实际上是创造了一个全新的String。
可以看下面的例子。
public class HelloWorld {
public static void main(String[] args) {
String s = "hello";
String sUpcase = s.toUpperCase();
String world = "world";
System.out.println(s+world);
}
}
短短的几行代码,在堆中就创建了四个对象,如果需要做大量的字符串拼接操作,内存消耗巨大。既然是多个对象,在System.out.println(s+world);
这一步的时候,java是如何工作的呢?
通过JDK自带的工具javap反编译以上代码:
实际上在开始时,系统就创建了一个StringBuilder
,并且通过该类的append()
方法将各个新创建的字符串拼接起来,并且最后调用toString()方法,生成结果。
该说法也在java api中得到了验证,下面是官方api的原文:
The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. String concatenation is implemented through the StringBuilder(or StringBuffer) class and its append method.
在非循环的字符串拼接中,+
和StringBuilder
性能基本相当。
但是当在多次循环中做字符串+
的拼接式,+会远远比StringBuilder
慢,因为每进入一个循环,系统都会new StringBuilder()
,再进行拼接。因此在多次循环中做字符串拼接,推荐使用StringBuilder
。
2. StringBuffer
StringBuffer是线程安全的可变的字符串。该类的每个方法中都加上了synchronize,因此性能比StringBuilder稍差。
3. StringBuilder
StringBuilder
是可变的字符串。该类与StringBuffer
用法基本相同,但是前者不保证线程安全,后者是线程安全的。我们都知道线程安全的操作都是和锁相关联的,每次操作都会涉及到上锁,必定会造成操作的缓慢,因此StringBuilder
比StringBuffer
性能更高。
在不需要保证线程安全的情况下,StringBuilder
比StringBuffer
适用性更广。