文章目录
概述
StringBuilder 从类名语义上来说 String 构建者,用来创建 String 的。在 java 开发中经常用到 String 处理字符串,但 String 对象是一个常量,一旦创建后不能改变,所以无法对其进行修改操作,对 String 对象的操作,实际上是不断的创建新的 String 对象。当需要对字符串的值进行频繁修改时,就需要使用 StringBuffer 和 StringBuilder 了。
StringBuilder
类的定义
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
构造方法
无参构造方法
public StringBuilder() {
super(16); // 调用父类的构造方法,初始容量为16个字符
}
String参数构造方法
public StringBuilder(String str) {
super(str.length() + 16); //调用父类的构造方法,初始容量为字符串长度加16个字符
append(str);
}
int参数构造方法
public StringBuilder(int capacity) {
super(capacity); //调用父类的构造方法,初始容量为指定大小.
}
CharSequence参数构造方法
public StringBuilder(CharSequence seq) {
this(seq.length() + 16); // 调用int参数构造方法
append(seq);
}
其他方法
writeObject
// 在进行序列化的时候保存StringBuilder对象的状态到一个流中
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
s.defaultWriteObject();
s.writeInt(count);
s.writeObject(value);
}
readObject
// 在进行反序列化时从流中获取StringBuild对象序列化之前的状态
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
count = s.readInt();
value = (char[]) s.readObject();
}
toString
实现父类的抽象方法
@Override
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
返回 StringBuilder 对象的字符串形式,创建了一个新的字符串对象,代码注释说了创建一个副本,而不要去共享这个内部维护的数组。因为返回的是 String 对象,是不可变的,如果返回的是共享的数组,在改变 StringBuilder 对象时,String 对象的内容随之改变,这就破坏了 String 对象的不可变性。
其他
StringBuilder 类中其它的方法都属于重写或继承自父类 AbstractStringBuilder 中的方法,重写的方法就是简单的调用了父类的实现而已。比如 append 方法:
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
需要注意一点的是 StringBuilder 是线程不安全的,在单线程程序中使用效率会高很多。在多线程程序中要慎用。
StringBuffer
StringBuffer 类也是用来构建动态 String 对象的,但与 StringBuilder 不同的是 StringBuffer 是线程安全的。
类的定义
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
成员变量
private transient char[] toStringCache;
toStringCache 变量用于缓存 StringBuffer 对象维护的字符数组,作用是保证线程操作 StringBuffer 对象时都能让 toString 方法表现出相同的结果。
构造方法
同 StringBuilder 中的构造方法
其他方法
writeObject
// 在进行序列化的时候保存StringBuffer对象的状态到一个流中
private synchronized void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
java.io.ObjectOutputStream.PutField fields = s.putFields();
fields.put("value", value);
fields.put("count", count);
fields.put("shared", false);
s.writeFields();
}
readObject
// 在进行反序列化时从流中获取StringBuffer对象序列化之前的状态。
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
java.io.ObjectInputStream.GetField fields = s.readFields();
value = (char[])fields.get("value", null);
count = fields.get("count", 0);
}
toString
实现父类的抽象方法
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
实现 CharSequence 接口的方法
@Override
public synchronized int length() {
return count;
}
@Override
public synchronized char charAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
return value[index];
}
@Override
public synchronized CharSequence subSequence(int start, int end) {
return super.substring(start, end);
}
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
重写的方法
StringBuffer 在重写父类 AbstractStringBuilder 的方法时,通过在方法上加上 synchronized
来保证线程安全。其实现逻辑就是简单的调用父类的实现而已。比如 append 方法:
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
如果数组发生了增删改操作,需要先清楚字符数组变量 toStringCache
。