小编典典

字符串连接:concat() 与“+”运算符

all

假设字符串 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);
    }
}

阅读 100

收藏
2022-03-09

共1个答案

小编典典

不,不完全是。

首先,语义上略有不同。如果anull,则a.concat(b)抛出 aNullPointerExceptiona+=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方法就会获胜,至少在性能方面是这样。

StringStringBuilder(及其包私有基类)的源代码可在 Sun JDK 的 src.zip 中找到。您可以看到您正在构建一个
char 数组(根据需要调整大小),然后在创建 final 时将其丢弃String。在实践中,内存分配速度惊人。

更新: 正如 Pawel Adamski 所说,最近的 HotSpot
的性能发生了变化。javac仍然产生完全相同的代码,但字节码编译器作弊。简单的测试完全失败,因为整个代码体都被丢弃了。Summing
System.identityHashCode(not String.hashCode)
显示StringBuffer代码有一点优势。下一次更新发布或您使用不同的 JVM
时可能会发生变化。

2022-03-09