java - 字符串连接:concat()vs“+”运算符

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


最佳答案:

不,不完全是。
首先,语义学上有点不同。如果anull,那么a.concat(b)会抛出一个NullPointerExceptiona+=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方法至少在性能方面会获胜。
sun jdk的src.zip中提供了StringStringBuilder的源代码(及其包私有基类)。您可以看到您正在构建一个char数组(根据需要调整大小),然后在创建finalString时将其丢弃。实际上,内存分配速度惊人。
更新:正如PawelAdamski指出的,性能在最近的热点发生了变化。javac仍然生成完全相同的代码,但字节码编译器会作弊。简单的测试完全失败,因为整个代码体都被丢弃了。summingSystem.identityHashCode(notString.hashCode)显示StringBuffer代码有一点优势。当下一个更新发布时,或者如果您使用不同的JVM,则可能发生更改。从@lukasedera list of HotSpot JVM intrinsics开始。