假设字符串 a 和 b:
a += b
a = a.concat(b)
在引擎盖下,它们是一样的吗?
这里是concat反编译作为引用。我也希望能够反编译 +
运算符,看看它做了什么。
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()
方法接受的内容更加严格。
要深入了解,请使用 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 #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
方法会胜出,至少在性能方面是这样。
String
和 StringBuilder
(及其包私有(private)基类)的源代码可在 Sun JDK 的 src.zip 中找到。您可以看到您正在构建一个 char 数组(根据需要调整大小),然后在创建最终 String
时将其丢弃。在实践中,内存分配速度惊人。
更新: 正如 Pawel Adamski 所说,最近的 HotSpot 的性能发生了变化。 javac
仍然产生完全相同的代码,但字节码编译器会作弊。简单的测试完全失败,因为整个代码体都被丢弃了。对 System.identityHashCode
求和(不是 String.hashCode
)表明 StringBuffer
代码有一点优势。下一次更新发布或您使用不同的 JVM 时可能会发生变化。来自 @lukaseder , a list of HotSpot JVM intrinsics .
关于java - 字符串连接 : concat() vs "+" operator,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47605/