当提到 StringBuffer 和 StringBuilder 时,首先会想到String ,String的值不可变,每次对string 操作都会产生出一个新的对象,然后将指针指向新的对象,而StringBuffer 和StringBuilder 类的对象能够多次被改变而不产生新的对象。
String的拼接是每次拼接都会去将原来的字符串和新字符串合并创建一个新的对象,创建的对象并不可变,StringBuilder 和StringBuffer 都是创建一个可变的动态对象,字符串的拼接中不需要创建新的对象,所谓的可变就是 内部是一个实现动态扩容的char[],他们之间类似于数组和 ArrayList,所以在效率上 String 是远低于 StringBuffer 和StringBuilder的。
而 StringBuffer 和 StringBuilder 的区别就在于线程安全,StringBuffer出现的早,线程安全(同步),适合并发场景中使用,而 StringBuilder 出现的晚于 StringBuffer ,非线程安全(非同步),效率更高 适合单线程场景,日常开发大多时候为单线程场景,所以使用StringBuilder 也较多一些,但是很多不理解多线程场景的人为保险起见都会使用StringBuffer
区别1:线程安全
StringBuffer:线程安全,StringBuilder:非线程安全。因为StringBuffer 的所有公开方法都是 synchronized 修饰的,而 StringBuilder 并没有 synchronized 修饰。
StringBuffer 代码片段:
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
区别2:缓冲区
StringBuffer 代码片段:
private transient char[] toStringCache;
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
StringBuilder 代码片段:
@Override
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
可以看出,StringBuffer 每次获取 toString 都会直接使用缓存区的 toStringCache 值来构造一个字符串。而 StringBuilder 则每次都需要复制一次字符数组,再构造一个字符串。
所以,缓存也是对 StringBuffer 的一个优化吧,不过 StringBuffer 的这个toString 方法仍然是同步的。
区别3:性能
既然 StringBuffer 是线程安全的,它的所有公开方法都是同步的,StringBuilder 是没有对方法加锁同步的,所以毫无疑问,StringBuilder 的性能要远大于 StringBuffer。
总结
所以,StringBuffer 适用于用在多线程操作同一个 StringBuffer 的场景,如果是单线程场合 StringBuilder 更合适。