Java字符串生成器附加计算
当我使用StringBuilder的append时,实际的复制何时发生?当我调用append时,还是当我将生成器作为字符串计算时Java字符串生成器附加计算,java,concatenation,stringbuilder,Java,Concatenation,Stringbuilder,当我使用StringBuilder的append时,实际的复制何时发生?当我调用append时,还是当我将生成器作为字符串计算时 我这样问是因为在我的应用程序中有很多log.debugstrA+strB+。。。我希望避免对生产代码中的串联进行求值。我知道java优化了+ops并将它们转换为字符串生成器的附加,但我不知道在附加函数中是否真的发生了连接。StringBuilder包含一个字符数组。append向该数组添加字符。显式或隐式调用stringBuilderInstance.toString
我这样问是因为在我的应用程序中有很多log.debugstrA+strB+。。。我希望避免对生产代码中的串联进行求值。我知道java优化了+ops并将它们转换为字符串生成器的附加,但我不知道在附加函数中是否真的发生了连接。StringBuilder包含一个字符数组。append向该数组添加字符。显式或隐式调用stringBuilderInstance.toString后,将根据stringbuilder的内容创建一个新的字符串实例。在stringbuilder中,当您附加时,这意味着您正在连接字符串。否,额外对象是在内部创建的。这只是附加!使用.toString将StringBuilder转换为字符串时,内容会从StringBuilder复制到字符串对象 两者都有。当您附加到StringBuilder时,您正在将字符复制到其内部字符数组中。将生成器转换为字符串时,将内容复制到字符串实例的内部数组中。StringBuilder扩展了AbstractStringBuilder,其中有几个附加方法:
public AbstractStringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
public AbstractStringBuilder append(StringBuffer sb) {
if (sb == null)
return appendNull();
int len = sb.length();
ensureCapacityInternal(count + len);
sb.getChars(0, len, value, count);
count += len;
return this;
}
AbstractStringBuilder append(AbstractStringBuilder asb) {
if (asb == null)
return appendNull();
int len = asb.length();
ensureCapacityInternal(count + len);
asb.getChars(0, len, value, count);
count += len;
return this;
}
@Override
public AbstractStringBuilder append(CharSequence s) {
if (s == null)
return appendNull();
if (s instanceof String)
return this.append((String)s);
if (s instanceof AbstractStringBuilder)
return this.append((AbstractStringBuilder)s);
return this.append(s, 0, s.length());
}
它使用char[]值;声明以声明所有字符的存储。
追加新字符串时,它会检查值数组的当前长度,如有必要,它会调用ensureCapacityInternal:
并在必要时调用expandCapacity:
/**
* This implements the expansion semantics of ensureCapacity with no
* size check or synchronization.
*/
void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2;
if (newCapacity - minimumCapacity < 0)
newCapacity = minimumCapacity;
if (newCapacity < 0) {
if (minimumCapacity < 0) // overflow
throw new OutOfMemoryError();
newCapacity = Integer.MAX_VALUE;
}
value = Arrays.copyOf(value, newCapacity);
}
结论:追加新数据时正在调用复制,字符值数组的容量不足以存储此新数据。您应该看看slf4j,它有采用字符串格式的日志方法和要替换的对象。连接发生在append函数中。
/**
* This implements the expansion semantics of ensureCapacity with no
* size check or synchronization.
*/
void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2;
if (newCapacity - minimumCapacity < 0)
newCapacity = minimumCapacity;
if (newCapacity < 0) {
if (minimumCapacity < 0) // overflow
throw new OutOfMemoryError();
newCapacity = Integer.MAX_VALUE;
}
value = Arrays.copyOf(value, newCapacity);
}