jdk1.0
StringBuffer类是一个具体类,继承了AbstractStringBuiler抽象类,实现了序列化接口和可读字符序列接口。
该类被final,不能被继承和重写里面的方法,可变字符序列,效率低,线程安全。
之前已经有了StringBuilder类,为什么还需要StringBuffer类,因为StringBuilder类在多线程的情况下就会出现问题,所以添加了一个新的类StringBuffer。在每个类可能出现并发问题的方法中添加synchronized同步锁,因此性能比StringBuilder类更低。
一、成员属性
private transient char[] toStringCache;
static final long serialVersionUID = 3388685877147921107L;
和StringBuilder类的一个区别,多了一个toStringCache字段,该字段是用于toString方法的。我们知道toString方法重新生成的String对象,会共享StringBuffer对象中的toStringCache属性,每次对StringBuffer进行修改,都会将其置为null。
二、构造方法
public StringBuffer() {
super(16);
}
public StringBuffer(int capacity) {
super(capacity);
}
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
public StringBuffer(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}
和StringBuilder类类似。默认初始化16个容量存放字符,如果是字符串或者可读字符序列,在其长度的基础上再加上16个空间。
三、主要方法
3.1 ensureCapacity(int)
@Override
public synchronized void ensureCapacity(int minimumCapacity) {
super.ensureCapacity(minimumCapacity);
}
在append、insert时需要考虑容量的问题,同时也需要考虑线程的安全问题,因此添加了同步关键字,其底层逻辑基本不变。
四、常用方法
4.1 toString()
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
根据缓存toStringCache来创建字符串对象。会维护每次最新字符串,如果缓存为空,通过会拷贝,否则根据缓存进行创建一个字符串。
4.2 charAt(int)
@Override
public synchronized char charAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
return value[index];
}
返回指定索引位置的字符。
4.3 getChars(int,int,char[],int)
@Override
public synchronized void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin){
super.getChars(srcBegin, srcEnd, dst, dstBegin);
}
得到字符串中的字符数组。调用的是抽象类AbstractStringBuilder中的方法,实现的原理:调用了数组的拷贝方法。
4.4 append(String)
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
向字符串后面追加一个字符串。使用了同步锁,线程安全。具体的实现是调用父类中的逻辑,其中将缓存进行了清空操作。
4.5 replace(int,int,String)
@Override
public synchronized StringBuffer replace(int start, int end, String str) {
toStringCache = null;
super.replace(start, end, str);
return this;
}
在指定的一块区域替换为一个字符串,起始位置前和结束位置后的字符串保持不变,只有中间部分的字符串会被取代。线程安全,具体实现调用父类中的方法。
4.6 substring(int,int)
@Override
public synchronized String substring(int start, int end) {
return super.substring(start, end);
}
返回字符串中的子串。
4.7 indexOf(String,int)
@Override
public synchronized int indexOf(String str, int fromIndex) {
return super.indexOf(str, fromIndex);
}
返回指定字符串在原字符串中的位置,开始查找位置可以我们自己提供。
4.8 reverse()
@Override
public synchronized StringBuffer reverse() {
toStringCache = null;
super.reverse();
return this;
}
将字符串进行反转。
五、序列化与反序列化
private static final java.io.ObjectStreamField[] serialPersistentFields =
{
new java.io.ObjectStreamField("value", char[].class),
new java.io.ObjectStreamField("count", Integer.TYPE),
new java.io.ObjectStreamField("shared", Boolean.TYPE),
};
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);
}
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();
}
遇到的问题
- toStringCache是什么时候被赋值的或者进行修改的。
- 什么是序列化与反序列化