StringBuffer类和StringBuilder类类似,都是为了可变字符串操作而定义的类类型,该类在字符串体系里面和StringBuilder类似。该类大致位置如下:StringBuffer类类型也是继承至统一的可变字符串抽象类AbstractStringBuilder,同时也实现了统一的字符序列标准接口类。
这里标准的字符序列接口类CharSequence是公共类型的,它定义了字符序列的基本接口,便于扩展给开发者自己实现相关字符串的操作封装定义,即在该接口体系下,外部开发者或者第三方库的提供者也可以在该接口上统一的扩展。
前面分析StringBuilder类已经说明过,认识一个类类型,需要从该类在体系设计中的定位,该类的基本数据结构,以及围绕该基本数据结构而定义的操作这三个方面来入手,在使用过程中逐一加深理解。
那么StringBuffer类类型,同样继承至统一的抽象的字符串操作类AbstractStringBuilder,从这几个方面分析来看:
1.StringBuffer基本数据结构
/**
* The value is used for character storage.
*/
char[] value;
/**
* The count is the number of characters used.
*/
int count;
同样继承至AbstractStringBuilder抽象类,该类的结构定义了基本字符串的存储结构,字符类型的数组value。另外定义了整型count,用于记录该数组中已经存放的字符数量。
2.StringBuffer对象构建
同样StringBuffer类的构造方法也分为四类:
1)默认构造对象方法
public StringBuffer() {
super(16);
}
该构造方法,内部通过super使用了父类AbstractStringBuilder的指定容量构造对象方法。默认情况下构造的对象,定义了存放16个字符的数组存储空间。
2)指定容量构造对象方法
public StringBuffer(int capacity) {
super(capacity);
}
该构造方法,允许构造对象的使用者在定义对象的时候指定其容量大小,来定义内部的存储结构的空间。
这里开放的方法是具有一定的意义,假如你的应用程序处理字符串在特殊场景下经常会超过默认定义的长度,那么指定合适的容量,会带来性能上的一定的优化,毕竟如果字符串操作经常超过默认长度,那会带来扩容的开销。
3)初始化字符串构造对象方法
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
该构造方法,允许构造对象的使用者在定义对象的时候初始化字符串值,这里和StringBuilder相同,都使用了父类的封装方法,这里字符数组存储容量是初始化字符串长度+默认长度16个字符的容量之和。
第一步先定义分配字符数组的容量;
第二步通过append方法将初始化字符串str对象追加到该字符数组中去。
4)初始化字符序列构造对象方法
public StringBuffer(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}
该构造方法,允许构造对象的使用者在定义对象的时候初始化字符序列对象,这个字符序列因为是开放的接口,意味着我们可以以第三方使用者来定义字符序列具体实现类类型的方式来初始化该字符串对象。
同样第一步是先定义分配字符数组的容量;
第二步通过append方法将初始化字符串seq对象追加到该字符数组中去。
3.StringBuffer与StringBuilder本质区别
既然已经有StringBuilder这样的可变字符串操作类补充String字符串操作的能力,那么为何还需要StringBuffer呢?
那是因为围绕字符串存储数据结构操作也可能存在多线程更新操作的场景,那么StringBuffer扩充出来的类类型实现是补充在多线程场景下对单个字符串对象操作的场景能力。如常用的append字符串追加拼凑的方法:
public synchronized StringBuffer append(StringBuffer sb) {
super.append(sb);
return this;
}
定义的方法之前有个java关键字synchronized,该关键字是java内置提供的并发控制的关键字能力。
多线程环境下,使用该操作由于synchronized关键字存在,那么会控制线程在该字符串对象操作上的并发控制,即串行处理的控制。
总结:
StringBuffer是StringBuilder在多线程环境下并发控制实现,正常情况下在字符串的操作上大多数情况下都是单线程操作,字符串操作对象的定义,字符串的具体操作等都是非多线程场景,这是因为字符串通常会作为数据处理的一个最小单元来定义,因此一个字符串的操作大多数情况下是一个线程数据的完整操作单元。
大多数情况下,我们设计应用时尽量是避免共享部分的,因为共享会涉及在并发的情况下的串行控制,所以StringBuilder是我们字符串操作中常用的类类型。