StringBuffer 源码分析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了StringBuffer 源码分析相关的知识,希望对你有一定的参考价值。

StringBuffer继承了AbstractStringBuilder,我们主要来看下AbstractStringBuilder这个类:

AbstractStringBuilder

1)、成员

/**
* The value is used for character storage.
*/
char value[];

/** 
* The count is the number of characters used.
*/
int count;

2)、方法

1、提供了两种构造器

AbstractStringBuilder() {
}


AbstractStringBuilder(int capacity) {
value = new char[capacity];
}

可以看出,第二种构造器可以在构造对象的时候就指定维护的数组的初始大小

2、扩容

public void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > value.length) {
expandCapacity(minimumCapacity);
}
}

void expandCapacity(int minimumCapacity) {
int newCapacity = (value.length + 1) * 2;
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
} else if (minimumCapacity > newCapacity) {
newCapacity = minimumCapacity;
}
value = Arrays.copyOf(value, newCapacity);
}

可以看出,如果维护的数组的长度不够,则会将长度变为原来的两倍

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

减少数组的长度到元素的个数

4public void setLength(int newLength) {
if (newLength < 0)
throw new StringIndexOutOfBoundsException(newLength);
if (newLength > value.length)
expandCapacity(newLength);

if (count < newLength) {
for (; count < newLength; count++)
value[count] = ‘\0‘;
} else {
count = newLength;
}
}

设置sequence长度

5、append方法

public AbstractStringBuilder append(String str) {
if (str == null) str = "null";
int len = str.length();
if (len == 0) return this;
int newCount = count + len;
if (newCount > value.length)
expandCapacity(newCount);
str.getChars(0, len, value, count);
count = newCount;
return this;
}

//本方法是StringBuffer append方法的核心,主要就是在扩容后,将append的字符串直接拷贝到扩容后的数组的相关位置上,并没有new其他不需要的对象

public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
if (srcBegin < 0) {
throw new StringIndexOutOfBoundsException(srcBegin);
}
if (srcEnd > count) {
throw new StringIndexOutOfBoundsException(srcEnd);
}
if (srcBegin > srcEnd) {
throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
}
System.arraycopy(value, offset + srcBegin, dst, dstBegin,
srcEnd - srcBegin);
}

这里与String拼接字符串的方式做一下比较:

String在进行“+”拼接时,会new临时的StringBuffer对象,即  new StringBuilder().append(str).append("asjdkla").toString(),一旦在循环中做拼接字符串的操作,那么将会new大量StringBuffer和String(StringBuffer的toString方法会new String),导致开销极大

下面我们再看下String的concat方法

public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
char buf[] = new char[count + otherLen];
getChars(0, count, buf, 0);
str.getChars(0, otherLen, buf, count);
return new String(0, count + otherLen, buf);
}

很明显,这种方式比使用“+”的方式好一些,但是还是new了多余的String对象,一旦在循环中调用,还是对性能有很大影响的

 

 

以上是关于StringBuffer 源码分析的主要内容,如果未能解决你的问题,请参考以下文章

[源码]String StringBuffer StringBudliderStringBuffer StringBuilder源码分析

String-StringBuffer-StringBuilder的区别和源码分析

STRING-STRINGBUFFER-STRINGBUILDER的区别和源码分析

java.util.AbstractStringBuilder源码分析

StringBuilder 源码分析

JAVA面试题 StringBuffer和StringBuilder的区别,从源码角度分析?