问题描述
假设字符串 a 和 b:
Assuming String a and b:
a += b
a = a.concat(b)
在幕后,它们是一回事吗?
Under the hood, are they the same thing?
这里是 concat 反编译作为参考.我也希望能够对 +
运算符进行反编译,看看它的作用.
Here is concat decompiled as reference. I'd like to be able to decompile the +
operator as well to see what that does.
public String concat(String s) {
int i = s.length();
if (i == 0) {
return this;
}
else {
char ac[] = new char[count + i];
getChars(0, count, ac, 0);
s.getChars(0, i, ac, count);
return new String(0, count + i, ac);
}
}
推荐答案
不,不完全.
首先,语义略有不同.如果 a
是 null
,则 a.concat(b)
抛出一个 NullPointerException
但 a+=b
会将 a
的原始值视为 null
.此外,concat()
方法只接受 String
值,而 +
运算符会默默地将参数转换为字符串(使用 对象的 toString()
方法).所以 concat()
方法在它接受的内容上更加严格.
Firstly, there's a slight difference in semantics. If a
is null
, then a.concat(b)
throws a NullPointerException
but a+=b
will treat the original value of a
as if it were null
. Furthermore, the concat()
method only accepts String
values while the +
operator will silently convert the argument to a String (using the toString()
method for objects). So the concat()
method is more strict in what it accepts.
为了深入了解,编写一个简单的类 a += b;
To look under the hood, write a simple class with a += b;
public class Concat {
String cat(String a, String b) {
a += b;
return a;
}
}
现在使用 javap -c
(包含在 Sun JDK 中)进行反汇编.您应该会看到一个列表,包括:
Now disassemble with javap -c
(included in the Sun JDK). You should see a listing including:
java.lang.String cat(java.lang.String, java.lang.String);
Code:
0: new #2; //class java/lang/StringBuilder
3: dup
4: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
7: aload_1
8: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
11: aload_2
12: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: invokevirtual #5; //Method java/lang/StringBuilder.toString:()Ljava/lang/ String;
18: astore_1
19: aload_1
20: areturn
所以,a += b
等价于
a = new StringBuilder()
.append(a)
.append(b)
.toString();
concat
方法应该更快.但是,使用更多字符串时,StringBuilder
方法会胜出,至少在性能方面是这样.
The concat
method should be faster. However, with more strings the StringBuilder
method wins, at least in terms of performance.
String
和StringBuilder
(及其包私有基类)的源代码可以在Sun JDK 的src.zip 中找到.您可以看到您正在构建一个字符数组(根据需要调整大小),然后在创建最终的 String 时将其丢弃.在实践中,内存分配速度惊人.
The source code of String
and StringBuilder
(and its package-private base class) is available in src.zip of the Sun JDK. You can see that you are building up a char array (resizing as necessary) and then throwing it away when you create the final String
. In practice memory allocation is surprisingly fast.
更新: 正如 Pawel Adamski 所指出的,最近的 HotSpot 的性能发生了变化.javac
仍然生成完全相同的代码,但字节码编译器会作弊.简单的测试完全失败,因为整个代码体都被扔掉了.总结 System.identityHashCode
(不是 String.hashCode
)表明 StringBuffer
代码有一点优势.可能会在下一次更新发布时发生变化,或者如果您使用不同的 JVM.来自 @lukaseder,HotSpot JVM 内在函数列表.
Update: As Pawel Adamski notes, performance has changed in more recent HotSpot. javac
still produces exactly the same code, but the bytecode compiler cheats. Simple testing entirely fails because the entire body of code is thrown away. Summing System.identityHashCode
(not String.hashCode
) shows the StringBuffer
code has a slight advantage. Subject to change when the next update is released, or if you use a different JVM. From @lukaseder, a list of HotSpot JVM intrinsics.
这篇关于字符串连接:concat() 与“+";操作员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!