Java 字符串拼接原理

原文:Java 字符串拼接原理

我们知道 Java 可以直接使用加号+来拼接字符串。

字符串+拼接的本质是使用StringBuilder.append()(已在Java8测试通过),最终如果要赋值给字符串变量时,会调用toString()

/**
 * 字符串追加
 */
@Test
public void testStrAppend() {
    /*
     * + 之前先隐式实例化 StringBuilder 对象
     * 每次 + 都是 append,期间不会 toString
     * 最后赋值给字符串时,会隐式调用 toString() 得到结果字符串
     */
    String abc = "2";
    String def = "3";
    String str = "1" + abc + def;
    System.out.println(str);
}
字符串追加

特殊地,如果是字符串常量拼接,编译器会在编译期自动优化到一起,例如"1" + "2" + "3"会自动优化为"123"

使用+拼接字符串是 Java 语法糖。

/**
 * 字符串常量拼接
 */
@Test
public void testConstantAppend() {
    // 如果是常量相加,那么编译器在编译为 class 文件时,会自动优化为一个常量
    String str = "1" + "2" + "3";
}
常量拼接会自动优化到一起

还需要注意的是在循环中如果使用+=其实会造成StringBuilder重复创建,导致资源浪费,因为每次+=都会 new 一次StringBuilder,并隐式toString()赋值给原字符串对象。

/**
 * 在循环中追加字符串
 * 在循环中 += 会造成资源浪费
 */
@Test
public void testStrAppendInLoop() {
    /*
     * 循环中不推荐使用 +=
     * 每次 += 相当于实例化一个新的 StringBuilder,然后调用 append(oldStr)、append(newStr)、toString()
     * 产生大量的 StringBuilder 对象
     */
    String str = "";
    for (int i = 0; i < 100; i++) {
        str += i;
    }
    System.out.println(str);
}
循环中使用 += 每次都会创建 StringBuilder 导致资源浪费

总结:

对于字符串使用+拼接:

  1. 如果是常量相加,那么在编译器会自动合并为一个常量字符串(只要挨着的常量就会合并,前后声明不影响,例如"1" + "2" + def + "4" + "5"会自动合并为"12" + def + "45"

  2. 如果与变量相加,那么相加前会初始化StringBuilder对象,每次相加都append(str),如果赋值给String,最终会隐式调用toString()(即只在最后调用一次toString(),这是我们期望的)

需要注意的是,使用+=拼接,例如a += 123;等效于a = a + 123;,每次+=都会实例化一个新的StringBuilder对象,append(a).append(123)再隐式调用toString()(注意:每次+=因为要再次赋值给字符串a都会隐式toString())。

所以,如果在循环中使用+=,会产生大量StringBuilder对象(每次相加前都会实例化StringBuilder对象)和String对象(每次都会toString()),造成资源浪费。

最佳实践:

  1. 普通的字符串拼接,可以使用+拼接字符串(与手动创建StringBuilder对象,调用append()等效)

  2. 循环中字符串拼接,推荐手动创建StringBuilder对象调用append(),而不是+=(循环中+=会创建大量StringBuilderString对象)

posted @ 2024-07-08 00:34  Higurashi-kagome  阅读(1)  评论(0编辑  收藏  举报