前言
String、StringBuilder、StringBuffer都是我们常用的字符串类,那么StringBuilder是怎么实现的字符串拼接?又是怎么实现的删除字符?值得我们深入到源码中一探究竟!
StringBuilder类结构
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
…………省略很多源码…………
}
StringBuilder位于java.lang包中,直接父类是AbstractStringBuilder,实现了两个接口,一个是Serializable、另一个是CharSequence,StringBuilder不允许被继承,所以直接采用了final修饰!
AbstractStringBuilder类结构
abstract class AbstractStringBuilder implements Appendable, CharSequence {
……省略很多源码……
}
AbstractStringBuilder同样位于java.lang包中,它是个抽象类,实现了两个接口,一个是Appendable、另一个是CharSequence接口。如果你看过线程安全的StringBuffer(注意不是StringBuilder),你会知道StringBuilder与StringBuffer继承的同一个父类:AbstractStringBuilder,该父类已经写好了大部分功能,不过由于是抽象类,不能创建对象,需要由具体的子类才能产生对象,写到这里,我想你也能猜到,StringBuilder与StringBuffer功能相似,只是前者只能在单线程下使用,后者则可以在多线程使用,这是为什么呢?答案将在另一篇StringBuffer的文章中解答
StringBuilder类加载
当我们使用StringBuilder的时候,StringBuilder类会加载到JVM中,最先执行的代码,也是类加载阶段的代码,按照继承结构,类的加载顺序如下:Object类、AbstractStringBuilder类、StringBuilder类,在类加载的时候,所有静态成员会按照书写顺序执行,Object的代码我就不说了,从AbstractStringBuilder类、StringBuilder类,执行了下面这些代码
AbstractStringBuilder的静态成员
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
常量MAX_ARRAY_SIZE的值,表示StringBuilder对象持有的数组对象的最大容量值
StringBuilder的静态成员
static final long serialVersionUID = 4383685877147921099L;
常量serialVersionUID表示类序列号时的版本,防止不同的类版本
StringBuilder对象的创建
提供4个创建StringBuilder对象的构造方法,你可以根据自己的需求,选择对象的创建方式,稍后逐个分析每个构造方法,在此之前先分析创建StringBuilder对象时,哪些实例成员的代码会被执行
AbstractStringBuilder的实例成员
char[] value;
int count;
AbstractStringBuilder是StringBuilder的父类,其中定义的两个实例变量会初始化,而在StringBuilder类下则没有定义其它实例变量!
value 用于保存字符的数组对象
count 表示字符的数量
StringBuilder默认构造方法分析
public StringBuilder() {
super(16);
}
显示调用父类的1个参数的构造方法,并传入值为16,表示字符数量
父类AbstractStringBuilder的单个参数构造方法分析
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
value为当前对象持有的char数组,此处新创建一个char数组对象,传入的参数capacity,表示数组对象的容量
备注:如果当前创建的是StringBuilder对象,则当前对象为StringBuilder对象,因为父类为抽象类,是不能创建对象的!
StringBuilder指定数组容量的构造方法分析
public StringBuilder(int capacity) {
super(capacity);
}
用于指定数组初始化容量的构造方法,同样调用父类AbstractStringBuilder的1个参数的构造方法
StringBuilder指定字符序列的构造方法
public StringBuilder(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}
用于在创建StringBuilder对象时,直接添加一个字符串的方法
1、首先调用当前重载的另一个StringBuilder的构造方法,用于初始化char数组对象
2、接着调用append()方法完成字符序列的添加,将字符序列添加到字符数组对象中
append()方法分析
@Override
public StringBuilder append(CharSequence s) {
super.append(s);
return this;
}
1、首先调用父类AbstractStringBuilder的append()方法,完成添加工作
2、向调用者返回当前对象
这个添加字符的方法,稍后会在单独文章中分析
AbstractStringBuilder中的append()方法分析
@Override
public AbstractStringBuilder append(CharSequence s) {
if (s == null)
return appendNull();
if (s instanceof String)
return this.append((String)s);
if (s instanceof AbstractStringBuilder)
return this.append((AbstractStringBuilder)s);
return this.append(s, 0, s.length());
}
1、检查传入的字符序列对象
如果为null,直接调用appendNull()方法,并返回
2、检查字符序列对象的实际类型是否为String
如果为String,则调用当前重载的append()方法,传入的参数会进行强制转换,将CharSequence强制转换为String对象
3、检查字符序列对象的实际类型是否为AbstractStringBuilder
如果为AbstractStringBuilder,调用重载的append()方法,注意这次类型强行转为AbstractStringBuilder
4、兜底,即不为null、也不为String、也不是AbstractStringBuilder
调用重载的append()方法,传入3个参数
5、向调用者返回当前对象
备注:注意虽然返回的AbsractStringBuilder对象,但由于抽象类不能创建对象,所以实际是子类对象
StringBuilder指定字符串的构造方法分析
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
用于在创建StringBuilder对象时,并指定一个字符串
1、首先使用super调用父类AbstractStringBuidler的构造方法
此时主要是为了创建足够大的字符数组
2、添加字符串到字符数组中
使用的append()方法
总结
1、如果字符串经常改变(添加、删除、修改)当属使用StringBuilder
2、StringBuilder提供4种不同的构造方法,我们可以根据需求选择何时的构造方法创建StringBuilder对象
下篇将分析StringBuilder中的append()系列方法,用于添加字符