在java中使用StringBuffer时,我想知道append函数在需要重新分配空间时是如何实现的。
例如,如果我附加一个比当前分配的空间长的字符串,它如何在方法的详细信息中管理它?
在java中使用StringBuffer时,我想知道append函数在需要重新分配空间时是如何实现的。
例如,如果我附加一个比当前分配的空间长的字符串,它如何在方法的详细信息中管理它?
源代码包含在 JDK 下载中。只需查找 src.zip 文件(我的位于 Program Files (x86)\Java\jdk1.6.0_01\src.zip 中)。解压后直接到java/lang,可以查看StringBuffer.java、StringBuilder.java、AbstractStringBuilder.java。
在这个实现中,看起来像 AbstractStringBuilder 中的“expandCapacity”计算容量并执行 Arrays.copyOf() 来扩展缓冲区。有趣的是,首先检查 < 0 以防止溢出情况。
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);
}
Apache Harmony 实现依赖于AbstractStringBuilder
管理添加/删除的方法(StringBuffer extends AbstractStringBuilder
)。
AbstractStringBuilder
保留一个字符缓冲区(即char
s 的数组)来保存当前的“字符串”。当将任何对象的下一个字符串表示附加到此缓冲区时,它会检查缓冲区是否包含足够的空间,如果没有足够的空间,它会分配一个新的字符缓冲区,复制旧缓冲区,然后将新字符串添加到该缓冲区。我们可以从内部收集到enlargeBuffer
:
private void enlargeBuffer(int min) {
int newSize = ((value.length >> 1) + value.length) + 2;
char[] newData = new char[min > newSize ? min : newSize];
System.arraycopy(value, 0, newData, 0, count);
value = newData;
shared = false;
}
value
...并且当(保存 char 缓冲区的私有成员)的容量将被超出时,在任何附加方法中都会调用此方法:
final void append0(char chars[]) {
int newSize = count + chars.length;
if (newSize > value.length) {
enlargeBuffer(newSize);
}
System.arraycopy(chars, 0, value, count, chars.length);
count = newSize;
}
标准的 OpenJDK 实现非常相似。同样, StringBuffer 依赖于AbstractStringBuilder:
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);
}
请注意,Arrays.copyOf
复制字符数组value
用空字符填充它以获得总大小newCapacity
,这基本上相当于new char[...]
Harmony 方法中的调用。同样,expandCapacity
当没有足够的空间添加下一个字符串段时调用该方法:
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;
}