4

在java中使用StringBuffer时,我想知道append函数在需要重新分配空间时是如何实现的。

例如,如果我附加一个比当前分配的空间长的字符串,它如何在方法的详细信息中管理它?

4

2 回答 2

5

源代码包含在 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);
}
于 2010-10-21T02:25:56.343 回答
4

Apache Harmony 实现依赖于AbstractStringBuilder管理添加/删除的方法(StringBuffer extends AbstractStringBuilder)。

AbstractStringBuilder保留一个字符缓冲区(即chars 的数组)来保存当前的“字符串”。当将任何对象的下一个字符串表示附加到此缓冲区时,它会检查缓冲区是否包含足够的空间,如果没有足够的空间,它会分配一个新的字符缓冲区,复制旧缓冲区,然后将新字符串添加到该缓冲区。我们可以从内部收集到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;
}
于 2010-10-21T02:14:27.583 回答