StringBuffer源码分析
一.概述
StringBuffer是java中用来处理字符串的类。不同于String,StringBuffer保存的字符串可以进行修改,拼接,删除等操作。相比于StringBuilder,StringBuffer几乎所有方法都被synchronized关键字修饰,因此StringBuffer是线程安全的,同时效率也比StringBuilder低。
StringBuffer.java中的相关代码:
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
…
}
1.StringBuffer被final修饰,不能被继承。
2.继承了AbstractStringBuilder,StringBuffer中的方法基本都是通过AbstractStringBuilder实现。
3.实现了java.io.Serializable接口,可以进行序列化。
4. 实现了CharSequence接口,可以将字符串当成一个一个的字符处理。
二.源码分析
1.全局变量
StringBuffer.java中的相关代码:
// 缓存,保存最后一次调用toString方法返回的字符串
// 当StringBuffer内容发生变化,缓存被清除
private transient char[] toStringCache;
static final long serialVersionUID = 3388685877147921107L; // 用于序列化
// 需要序列化的字段,用于序列化
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),
};
2.常用的构造方法
1)无参数
StringBuffer.java中的相关代码:
public StringBuffer() {
super(16);
}
默认情况下,调用构造方法,会调用父类的构造方法,分配一个容量为16个字符空间。
2)参数为int
StringBuffer.java中的相关代码:
public StringBuffer(int capacity) {
super(capacity);
}
调用父类方法,指定需要分配的空间的大小来进行分配。
3)参数为String
StringBuffer.java中的相关代码:
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
调用父类的方法,为字符串分配空间,同时再多分配出来16个字符大小的空间,防止之后字符串长度发生改变;保存字符串。
3.length方法
获取StringBuffer中字符串的长度。
StringBuffer.java中的相关代码:
@Override
public synchronized int length() {
// 返回已使用空间的数量,count为父类的全局变量
return count;
}
4.capacity方法
获取StringBuffer当前最大能保存的字符串的长度。
StringBuffer.java中的相关代码:
@Override
public synchronized int capacity() {
// 返回字符数组长度,value为父类的全局变量
return value.length;
}
5. ensureCapacity方法
对字符数组进行扩容,保证空间大小足够。
StringBuffer.java中的相关代码:
@Override
public synchronized void ensureCapacity(int minimumCapacity) {
// 调用父类的ensureCapacity方法
super.ensureCapacity(minimumCapacity);
}
6.trimToSize方法
缩容,对字符数组中没有使用的空间进行释放。
StringBuffer.java中的相关代码:
@Override
public synchronized void trimToSize() {
// 调用父类的trimToSize方法
super.trimToSize();
}
7. setLength方法
设置字符数组空间的大小。
StringBuffer.java中的相关代码:
@Override
public synchronized void setLength(int newLength) {
// 清除缓存
toStringCache = null;
// 调用父类的setLength方法
super.setLength(newLength);
}
8. charAt方法
获取字符串中指定位置的字符。
StringBuffer.java中的相关代码:
@Override
public synchronized char charAt(int index) {
// 若指定位置小于0或指定位置超过了字符串的长度
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
// 返回指定位置的字符
return value[index];
}
9. setCharAt方法
设置字符串中指定位置index的字符为ch。
StringBuffer.java中的相关代码:
@Override
public synchronized void setCharAt(int index, char ch) {
// 若指定位置小于0或指定位置超过了字符串的长度
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
// 清除缓存
toStringCache = null;
// 设置字符
value[index] = ch;
}
10.append方法
向当前字符串后再拼接一个字符串。
1)参数为Object
StringBuffer.java中的相关代码:
@Override
public synchronized StringBuffer append(Object obj) {
// 清除缓存
toStringCache = null;
// 调用父类的append方法
super.append(String.valueOf(obj));
// 返回
return this;
}
2)参数为String
StringBuffer.java中的相关代码:
@Override
public synchronized StringBuffer append(String str) {
// 清除缓存
toStringCache = null;
// 调用父类的append方法
super.append(str);
// 返回
return this;
}
其它参数形式的append方法的执行流程,也都是先清除缓存,再调用父类的append方法,最后返回。
11.delete方法
删除字符串中start到end之间的字符。
StringBuffer.java中的相关代码:
@Override
public synchronized StringBuffer delete(int start, int end) {
// 清除缓存
toStringCache = null;
// 调用父类的delete方法
super.delete(start, end);
// 返回
return this;
}
12.replace方法
将原字符串中start和end中的字符替换为字符串str。
StringBuffer.java中的相关代码:
@Override
public synchronized StringBuffer replace(int start, int end, String str) {
// 清除缓存
toStringCache = null;
// 调用父类的replace方法
super.replace(start, end, str);
// 返回
return this;
}
13.substring方法
截取原字符串中从start开始到结束的字符串。
StringBuffer.java中的相关代码:
@Override
public synchronized String substring(int start) {
// 调用重载的方法。
return substring(start, count);
}
调用重载的substring方法。
截取原字符串中从start开始到end之间的字符串。
StringBuffer.java中的相关代码:
@Override
public synchronized String substring(int start, int end) {
// 调用父类的substring方法,并返回
return super.substring(start, end);
}
14.insert方法
在原字符串的offset位置插入字符串str。
StringBuffer.java中的相关代码:
@Override
public synchronized StringBuffer insert(int offset, String str) {
// 清除缓存
toStringCache = null;
// 调用父类的insert方法
super.insert(offset, str);
// 返回
return this;
}
其它参数形式的insert方法的执行流程,也都是先清除缓存,再调用父类的insert方法,最后返回。
15.indexOf方法
返回源字符串中str字符串首次出现的位置。
StringBuffer.java中的相关代码:
@Override
public int indexOf(String str) {
// 调用父类的indexOf方法,并返回
return super.indexOf(str);
}
该方法没有被synchronized方法修饰,因为indexOf方法还有一个重载的方法是被synchronized修饰的,可以根据需求自行选择。
类似的,lastIndexOf方法也提供了两个方法,一个被synchronized修饰,一个没有被synchronized修饰的方法。
16. reverse方法
将字符串进行反转。
StringBuffer.java中的相关代码:
@Override
public synchronized StringBuffer reverse() {
// 清除缓存
toStringCache = null;
// 调用父类的reverse方法
super.reverse();
// 返回
return this;
}
17. toString方法
将StringBuffer对象转换为String对象。
StringBuffer.java中的相关代码:
@Override
public synchronized String toString() {
// 若缓存为空
if (toStringCache == null) {
// 创建缓存,复制保存当前字符串的值。
toStringCache = Arrays.copyOfRange(value, 0, count);
}
// 根据缓存内容,创建字符串并返回
return new String(toStringCache, true);
}
18. writeObject方法
对StringBuffer对象进行序列化。
StringBuffer.java中的相关代码:
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();
}
19. readObject方法
对StringBuffer对象进行反序列化。
StringBuffer.java中的相关代码:
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);
}