字符串连接需要多少个内存位置?

时间:2013-11-28 09:18:22

标签: java string memory-management stringbuilder

字符串连接需要多少个内存位置?

String myStringVariable = "Hello";

以下两个陈述:

String s = "ABC" + "Hello" + "DEF";

String s = "ABC";
s = s + "Hello";
s = s + "DEF";

String s = "ABC" + myStringVariable + "DEF";

哪个会消耗更多内存?在哪种情况下StringBuilder最有用?

6 个答案:

答案 0 :(得分:3)

StringBuilder在任何情况下都是有用的,如编写的那样 - 编译器将尽可能重用相同的StringBuilder实例。当你在循环中添加字符串时,它略微有用。 (我说“略微”,因为大部分时间你并没有真正添加 许多字符串,也不是那个很长。差异会显示在微基准测试中但是你的程序不是一个,除非你正在编写一个模板引擎或类似的东西。)

创建垃圾StringBuilder并不会像GC压力那样“浪费内存”。事实上,像Java这样的世代清道夫GC被设计用于创建大量非常短暂的垃圾对象。我不担心,除非你真的在GC上花了太多时间。

String内容重复复制到StringBuilder s也是浪费,但再一次,不太可能在循环之外产生重大影响。

答案 1 :(得分:3)

第一个语句将由编译器转换为String s = "ABCDEF";,因此不会有连接

第二个语句将由编译器转换为此代码(或类似的东西)

    String s = "ABC";
    StringBuilder sb = new StringBuilder(s);
    sb.append("DEF");
    s = sb.toString();

答案 2 :(得分:2)

String s = "ABC" + "DEF";

在编译时解决,并且StringBuilder过去没有连接。

String s = "ABC";
s = s + "DEF";   

在这种情况下,StringBuilder(string...).toString()可以在运行时解析String

所以你需要使用StringBuilder,在你的情况下,它的性能差异可以忽略不计。

不要使用多少串联“+”,在较少量的连接中不会造成太大的伤害。如果你正在处理更大的数量,则更喜欢使用StringBuilder和append方法。

如果您将字符串在大范围内与+连接,则可以看到区别,然后转到StringBuilder追加。

答案 3 :(得分:2)

我创建了课程Main

public class Main {
    public String foo() {
        String s = "ABC" + "DEF";
        return s;
    }
    public String foo1() {
        String s = "ABC";
        s = s + "DEF";
        return s;
    }
}

并反编译:

public java.lang.String foo();
Signature: ()Ljava/lang/String;
Code:
   0: ldc           #2                  // String ABCDEF
   2: astore_1
   3: aload_1
   4: areturn

public java.lang.String foo1();
Signature: ()Ljava/lang/String;
Code:
   0: ldc           #3                  // String ABC
   2: astore_1
   3: new           #4                  // class java/lang/StringBuilder
   6: dup
   7: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
  10: aload_1
  11: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  14: ldc           #7                  // String DEF
  16: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  19: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  22: astore_1
  23: aload_1
  24: areturn

方法foo使串联字符串编译时,但方法foo1在运行时连接字符串并使用StringBuilder

首先示例使用更少的内存。

我使用Oracle JDK 1.7_45和默认属性。

答案 4 :(得分:1)

  

哪个会占用更多内存?

java规范15.8.1 String Concatenation Operator +:

  

除非表达式是a,否则新创建String对象(第12.5节)   编译时常量表达式(§15.28)。

     

实现可以选择执行转换和连接   在一步中避免创建然后丢弃中间体   字符串对象。增加重复字符串的性能   连接,Java编译器可以使用StringBuffer类或a   类似的技术减少了中间String对象的数量   通过评估表达式创建的。

  • 第一句话,

     String s = "ABC" + "Hello" + "DEF";
    

    此表达式是编译时常量表达式。将一步完成。在运行时没有创建对象。

  • 第二声明:

      String s = "ABC";
      s = s + "Hello";
      s = s + "DEF";
    

    此语句将创建一个包含"ABCHELLO"的新字符串。第三个语句将创建一个包含"ABCHELLODEF"的新字符串。此字符串连接将使用StringBuilder

  • 进行
  • 第三条陈述

    String s = "ABC" + myStringVariable + "DEF";
    

    与第一个语句不同,此语句将在运行时创建一个新实例,因为它不是编译时常量表达式。

但是使用StringBuilder来连接这样的三个字符串不会导致性能提升,除非你正在使用计数很重要的字符串数。

答案 5 :(得分:0)

当您想要使用字符串时,StringBuilder非常有用。通过组合字符串动态创建字符串它只会占据一个物体。

如果每次连接都使用字符串,则会在内存中创建新对象。