java - 字符串连接 : concat() vs "+" operator

标签 java string concatenation

假设字符串 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 方法会胜出,至少在性能方面是这样。

StringStringBuilder(及其包私有(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/

相关文章:

java - 如何在 Recyclerview 中单击按钮调用电话

java - 编辑字符串中的结果等于 false

MySQL 通配符与 concat 匹配

java - 使用 vector 数组创建矩阵数组的简单方法

javascript - 计算字符串中的大小写字符

mysql - MYSQL中存在空值时如何进行GROUP_CONCAT?

lua - Lua中表格的串联

java - Sqoop 导入 Java 客户端

java - GSON 将 boolean 值序列化为 0 或 1

Java JAMA 不兼容无法转换错误