这里从两方面比较:执行速度与线程安全
一、执行速度
StringBuilder > StringBuffer > String
注:
①String 是不可变的对象(String类源码中存放字符的数组被声明为final), 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。总而言之,也就是说使用String时新生成了string对象。而stringBuilder与stringBuffer不会生成新的对象。
② StringBuffer与StringBuilder,他们是字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在一个对象上操作的,不像String一样创建一些对象进行操作,所以速度就快了。
二、线程安全
StringBuilder:线程非安全的
StringBuffer:线程安全的
注:
①首先,stringbuilder和stringbuffer的父类都是AbstractStringBuilder,这里贴一下AbstractStringBuilder,StringBuilder,StringBuffer的append方法。
AbstractStringBuilder类
public AbstractStringBuilder append(Object obj) { return append(String.valueOf(obj)); } public AbstractStringBuilder append(String str) { if (str == null) str = "null"; int len = str.length(); ensureCapacityInternal(count + len); str.getChars(0, len, value, count); count += len; return this; } public AbstractStringBuilder append(StringBuffer sb) { if (sb == null) return append("null"); int len = sb.length(); ensureCapacityInternal(count + len); sb.getChars(0, len, value, count); count += len; return this; }
StringBuilder类
public StringBuilder append(Object obj) { return append(String.valueOf(obj)); } public StringBuilder append(String str) { super.append(str); return this; } private StringBuilder append(StringBuilder sb) { if (sb == null) return append("null"); int len = sb.length(); int newcount = count + len; if (newcount > value.length) expandCapacity(newcount); sb.getChars(0, len, value, count); count = newcount; return this; } public StringBuilder append(StringBuffer sb) { super.append(sb); return this; } public StringBuilder append(CharSequence s) { if (s == null) s = "null"; if (s instanceof String) return this.append((String)s); if (s instanceof StringBuffer) return this.append((StringBuffer)s); if (s instanceof StringBuilder) return this.append((StringBuilder)s); return this.append(s, 0, s.length()); } public StringBuilder append(CharSequence s, int start, int end) { super.append(s, start, end); return this; } public StringBuilder append(char[] str) { super.append(str); return this; } public StringBuilder append(char[] str, int offset, int len) { super.append(str, offset, len); return this; } public StringBuilder append(boolean b) { super.append(b); return this; } public StringBuilder append(char c) { super.append(c); return this; } public StringBuilder append(int i) { super.append(i); return this; } public StringBuilder append(long lng) { super.append(lng); return this; } public StringBuilder append(float f) { super.append(f); return this; } public StringBuilder append(double d) { super.append(d); return this; }
StringBuffer类
public synchronized StringBuffer append(Object obj) { super.append(String.valueOf(obj)); return this; } public synchronized StringBuffer append(String str) { super.append(str); return this; } public synchronized StringBuffer append(StringBuffer sb) { super.append(sb); return this; }
注:贴了部分代码,可以发现StringBuilder和StringBuffer的成员方法append都来自它们共同的父类,不同的是StringBuffer的append方法加了synchronized关键字,而stringbuilder的append方法没有,
这就是StringBuffer线程安全的原因当StringBuffer对象在字符缓冲区被多个线程使用时,append方法是可以用synchronized加锁的,保证其线程安全。但StringBuilder的append方法则没有该关键字,所以不能保证线程安全。
但是单线程时,还是要尽量使用速度快的StringBuilder。
综上所述,String,StringBuilder,StringBuffer的使用建议:
1.如果要操作少量的数据用 String
单线程操作字符串缓冲区 下操作大量数据 StringBuilder
多线程操作字符串缓冲区 下操作大量数据 StringBuffer
2.不要使用String类的"+"来进行频繁的拼接,因为那样的性能极差的,应该使用StringBuffer或StringBuilder类,这在Java的优化上是一条比较重要的原则。