JDK1.8源码解读之 AbstractStringBuilder

388 阅读3分钟

概述

源码的开头解释到,AbstractStringBuilder是一个可变的字符串序列。 长度和内容可以通过指定的方法进行修改。

继承关系

该类是抽象类,是StringBuffer类和StringBuilder类的父类。 实现了Appendable, CharSequence两个接口。

成员属性

char[] value; // 用来存储字符
int count; // 表示已尽使用过的字符串数量

构造器

有两个构造器,第一个是参数为空,第二个带有指定容量。

AbstractStringBuilder()
AbstractStringBuilder(int capacity)

关键方法

+ length()

返回字符串的长度,这里指的是实际字符的个数。

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

返回字符串的容量,是成员属性 value[]最多能存储多少个字符。

public int capacity() {
    return value.length;
}
+ ensureCapacity(int minimumCapacity)

将字符串扩容至指定容量。 具体扩容规则: 如果指定容量比当前容量还小,当然什么也不会发生。 如果指定容量比当前容量大,那么就扩容至指定容量。

public void ensureCapacity(int minimumCapacity) { ... } 
+ trimToSize()

将字符串的未使用的部分,

public void trimToSize() {
    if (count < value.length) {
        value = Arrays.copyOf(value, count);
    }
}

代码示例:

StringBuffer b = new StringBuffer("abc");
System.out.println(b.capacity());
b.trimToSize();
System.out.println(b.capacity());
>> 19
>> 3

新建时的容量是 实际长度3+16 = 19,使用trim后,容量为3。就是把没有实际内容的16个位置清除掉了。

+ setlength(int newLength)

设置长度为指定长度,以空格填充扩容的部分。

public void setLength(int newLength) { ... }
+ charAt(int index)

返回指定索引处的字符。

public char charAt(int index) { }
+ getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

将当前字符串复制到目标字符串。

public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) { ... }
append(Object obj)

将目标字符串添加到当前字符串末尾。

public AbstractStringBuilder append(Object obj) {
    return append(String.valueOf(obj));
}
delete(int start, int end)

移除指定范围内的字符。

public AbstractStringBuilder delete(int start, int end) { ... }
replace(int start, int end, String str)

将指定范围内的字符替换为目标字符。

public AbstractStringBuilder replace(int start, int end, String str) { ... }
insert(int index, char[] str, int offset, int len)

将指定范围内的字符插入到当前字符串的index位置处。

public AbstractStringBuilder insert(int index, char[] str, int offset, int len) { ... }
+ indexOf(String str)

计算目标字符串第一次出现的位置的索引值。

public int indexOf(String str) { ... }
+ lastIndexOf(String str)

计算目标字符串最后一次出现的位置的索引值。

public int lastIndexOf(String str) {
    return lastIndexOf(str, count);
}
+reverse()

将当前字符串倒置。

public AbstractStringBuilder reverse() { ... }

newCapacity(int minimumCapacity)

如果空间足够的话,会将容量扩大到 length * 2 + 2;

private int newCapacity(int minCapacity) {
    // overflow-conscious code
    int newCapacity = (value.length << 1) + 2;
    if (newCapacity - minCapacity < 0) {
        newCapacity = minCapacity;
    }
    return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
        ? hugeCapacity(minCapacity)
        : newCapacity;
}

实现原理

String类的底层是采用字符数组实现的。各种操作其实都是基于字符数组的操作。

结语

需要注意的地方是:AbstractStringBuilder是StringBuffer和StringBuilder的父类。最大的特点在于:可变。 append(),replace(),insert()方法内部,都会进行ensureCapacityInternal()的操作:当实际需要存储的字符,比当前容量大的时候,就会进行扩容。 可变的设计,实际上是对同一个value[]进行操作,而不是新建value[]。是为了避免在每次对字符串进行修改的时候,都新建char[]。频繁的新建char[],会带来大量的内存开销,同时给垃圾回收也需要占用一些内存资源。

希望和大家多多交流


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