JDK1.8源码解读之 StringBuffer

685 阅读3分钟

概述

源码开头注释说到,StringBuffer是一个线程安全的,可变的字符串序列。可在多线程中使用。

继承关系

继承自 AbstractStringBuilder 类 实现了 java.io.Serializable, CharSequence 接口

成员属性

private transient char[] toStringCache;

存储上一次ToString()得到的值,当StringBuffer被改变的时候,会被清除。其实是为了节省计算时间,不重复消耗计算能力。

构造器

最明显的特点就是新建一个StringBuffer后,会将容量指定为实际容量+16。

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);
}

关键方法

+ length()

获取StringBuffer实际字符的长度 继承重写了父类AbstractStringBuilder的length()方法。 方法体一样,仅仅是添加了 synchronized 修饰符。

@Override
public synchronized int length() {
    return count;
}
+ capacity()

获取当前 StringBuffer 的容量 继承重写了父类 AbstractStringBuilder 的 capacity()方法。 方法体一样,仅仅是添加了 synchronized 修饰符。

@Override
public synchronized int capacity() {
    return value.length;
}
+ ensureCapacity()

重写父类方法,使用父类的方法ensureCapacity进行扩容, 增加了synchronized修饰符。

@Override
public synchronized void ensureCapacity(int minimumCapacity) {
    super.ensureCapacity(minimumCapacity);
}
+ trimToSize()

重写父类方法,使用父类的方法trimToSize去除字符串末尾的空格,增加了synchronized修饰符。

@Override
public synchronized void trimToSize() {
    super.trimToSize();
}
+ setLength()

重写父类方法设置长度, 增加了synchronized修饰符。

@Override
public synchronized void setLength(int newLength) {
    toStringCache = null;
    super.setLength(newLength);
}
+ charAt()

返回指定位置处的字符

@Override
public synchronized char charAt(int index) {
    if ((index < 0) || (index >= count))
        throw new StringIndexOutOfBoundsException(index);
    return value[index];
}
+ append()

将指定对象添加到StringBuffer末尾,有很多重载方法,适应了不同的数据类型。

@Override
public synchronized StringBuffer append(Object obj) {
    toStringCache = null;
    super.append(String.valueOf(obj));
    return this;
}
+ delete()

删除指定位置范围内的字符

@Override
public synchronized StringBuffer delete(int start, int end) {
    toStringCache = null;
    super.delete(start, end);
    return this;
}
+ replace()

将指定位置范围处的字符替换为目标字符串

@Override
public synchronized StringBuffer replace(int start, int end, String str) {
    toStringCache = null;
    super.replace(start, end, str);
    return this;
}
+ substring()

获取子串,从start索引开始到末尾。

@Override
public synchronized String substring(int start) {
    return substring(start, count);
}
+ insert()

将字符串插入到指定位置。有很多重载方法

@Override
public synchronized StringBuffer insert(int offset, String str) {
    toStringCache = null;
    super.insert(offset, str);
    return this;
}
+ indexOf()

计算字符串第一次出现的位置。

@Override
public int indexOf(String str) {
    // Note, synchronization achieved via invocations of other StringBuffer methods
    return super.indexOf(str);
}
+ lastIndexOf()

计算字符串最后一次出现的位置。

@Override
public int lastIndexOf(String str) {
    // Note, synchronization achieved via invocations of other StringBuffer methods
    return lastIndexOf(str, count);
}
+ reverse()

返回StringBuffer的倒序排列。

@Override
public synchronized StringBuffer reverse() {
    toStringCache = null;
    super.reverse();
    return this;
}

实现原理

  1. 底层的存储结构,是和父类AbstractStringBuilder一样的,都是字符数组char[] value。
  2. 实现线程安全的主要途径,就是给对应的方法增加了synchronized修饰符。

常见问题

synchronized 的使用?

关键字synchronized可以保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,同时synchronized可以保证一个线程的变化可见(可见性),即可以代替volatile。 Java中每一个对象都可以作为锁,这是synchronized实现同步的基础: 普通同步方法(实例方法),锁是当前实例对象 ,进入同步代码前要获得当前实例的锁 静态同步方法,锁是当前类的class对象 ,进入同步代码前要获得当前类对象的锁 同步方法块,锁是括号里面的对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。

相关阅读

JDK1.8源码解读之 AbstractStringBuilder

希望和大家多多交流


我16年毕业以后,做的是前端,目前打算深入学习java开发。内容有任何问题,欢迎各位小伙伴们指正,也希望小伙伴们给我点赞和关注,给我留言,一起交流讨论,共同进步。