首先你的问题有问题:
String s = "orange";
s.append("apple");
这里创建了两个对象
正确,创建了两个对象,字符串“orange”和字符串“apple”,在 StringBuffer/StringBuilder 内,如果我们不溢出缓冲区,则不会创建任何对象。所以这些代码行创建了 2 或 3 个对象。
StringBuilder s = new StringBuilder("Orange");
s.append("apple");
现在这里只创建了一个对象
我不知道你从哪里得到的,在这里你创建了一个 StringBuilder 对象,一个“Orange”字符串,一个“apple”字符串,总共 3 个对象,如果我们溢出 StringBuilder 缓冲区则创建 4 个对象。 (我将数组创建视为对象创建)。
我读到你的问题是,StringBuilder 如何在不创建新对象的情况下执行附加操作(当缓冲区未溢出时)?
你应该看看StringBuilder
,因为它是非线程安全的实现。代码很有趣并且易于阅读。我已经添加了内嵌评论。
作为内部结构,有一个字符数组,而不是字符串。它最初的长度为 16,每次超出容量时都会增加长度。如果要附加的字符串适合 char 数组,则无需创建新对象。
StringBuilder
延伸AbstractStringBuilder http://grepcode.com/snapshot/repository.grepcode.com/java/root/jdk/openjdk/6-b14/,您将在其中找到以下代码:
/**
* The value is used for character storage.
*/
char value[];
由于并非所有数组都会在给定时间使用,因此另一个重要变量是长度:
/**
* The count is the number of characters used.
*/
int count;
Append 的重载有很多,但最有趣的是以下一个:
public AbstractStringBuilder append(String str) {
if (str == null) str = "null"; //will literally append "null" in case of null
int len = str.length(); //get the string length
if (len == 0) return this; //if it's zero, I'm done
int newCount = count + len; //tentative new length
if (newCount > value.length) //would the new length fit?
expandCapacity(newCount); //oops, no, resize my array
str.getChars(0, len, value, count); //now it will fit, copy the chars
count = newCount; //update the count
return this; //return a reference to myself to allow chaining
}
String.getChars http://download.oracle.com/javase/6/docs/api/java/lang/String.html#getChars%28int,%20int,%20char%5B%5D,%20int%29(int srcBegin, int srcEnd, char[] dst, int dstBegin) 将此字符串中的字符复制到目标字符数组中。
所以,append 方法非常简单,唯一需要发现的魔法就是expandCapacity
, 这里是:
void expandCapacity(int minimumCapacity) {
//get the current length add one and double it
int newCapacity = (value.length + 1) * 2;
if (newCapacity < 0) { //if we had an integer overflow
newCapacity = Integer.MAX_VALUE; //just use the max positive integer
} else if (minimumCapacity > newCapacity) { //is it enough?
//if doubling wasn't enough, use the actual length computed
newCapacity = minimumCapacity;
}
//copy the old value in the new array
value = Arrays.copyOf(value, newCapacity);
}
数组.copyOf http://download.oracle.com/javase/6/docs/api/java/util/Arrays.html#copyOf%28char%5B%5D,%20int%29(char[] Original, int newLength) 复制指定的数组,并用空字符截断或填充(如有必要),以便副本具有指定的长度。
在我们的例子中,填充,因为我们正在扩大长度。