从特性入手进行区别
(1)线程安全性
String和StringBuffer都是线程安全的,而StringBuilder线程不安全
1.String默认把数据都以常量形式保存,放在了常量池中,且是final修饰的类,是不可变的,所以是线程安全的。
2.StringBuffer 的所有公开方法都是 synchronized 修饰的,而 StringBuilder 并没有。
// StringBuffer的代码片段:
@Override
public synchronized StringBuffer append(Object obj) {
toStringCache = null;
super.append(String.valueOf(obj));
return this;
}
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
// StringBuilder的代码片段:
@Override
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
(2)执行效率
1.String 是final对象,不会被修改,大部分操作都需要创建新的对象,而不是改变原来的对象;所以效率很低是三者之中最差的。
2.StringBuffer 的所有公开方法都是同步的,速度是比String快,但次于StringBuilder。
如下,StringBuffer 每次获取 toString 都会直接使用缓存区的 toStringCache 值来构造一个字符串缓存冲,这也是对 StringBuffer 的一个优化吧。不过,方法只要加了synchronized同步,效率就是比不加synchronized的低。
// StringBuffer 代码片段:
private transient char[] toStringCache;
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
3. StringBuilder 是没有对方法加锁同步的,所以毫无疑问,StringBuilder的性能要远大于StringBuffer。
如下 StringBuilder 则每次都需要复制一次字符数组,再构造一个字符串。
// StringBuilder 代码片段:
@Override
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}