不完全正确。
首先,语义上略有不同。如果a
为null
,则a.concat(b)
会抛出NullPointerException
,但a+=b
会将a
的原始值视为null
。此外,concat()
方法仅接受String
值,而+
运算符将默默地将参数转换为字符串(对于对象,使用toString()
方法)。因此,concat()
方法在其接受的内容方面更为严格。
要深入了解,请编写一个带有a += b;
的简单类。
public class Concat {
String cat(String a, String b) {
a += b;
return a;
}
}
现在使用javap -c
(包含在Sun JDK中)进行反汇编。您应该能够看到一个包括以下内容的列表:
java.lang.String cat(java.lang.String, java.lang.String);
Code:
0: new
3: dup
4: invokespecial
7: aload_1
8: invokevirtual
11: aload_2
12: invokevirtual
15: invokevirtual
18: astore_1
19: aload_1
20: areturn
因此,a += b
相当于
a = new StringBuilder()
.append(a)
.append(b)
.toString();
concat
方法应该更快。然而,随着字符串数量的增加,
StringBuilder
方法在性能方面获胜,至少在这方面是如此。
String
和
StringBuilder
(以及它的包私有基类)的源代码在 Sun JDK 的 src.zip 中可用。你可以看到你正在建立一个字符数组(根据需要调整大小),然后在创建最终的
String
时将其丢弃。实际上,内存分配非常快速。
更新:正如 Pawel Adamski 所指出的那样,在更近期的 HotSpot 中性能已经发生了变化。
javac
仍然生成完全相同的代码,但是字节码编译器作弊了。简单的测试完全失败,因为整个代码体被抛弃了。对
System.identityHashCode
(而不是
String.hashCode
)求和显示
StringBuffer
代码具有轻微优势。在下一次更新发布时或者使用不同的 JVM 时可能会发生变化。来自
@lukaseder,
HotSpot JVM 内在函数列表。
+
是否可被反编译。 - Galen NareStringBuffer
或StringBuilder
(线程不安全但更快) - Ujjwal Singh