内存中创建了多少个字符串?

时间:2015-02-25 21:05:48

标签: java string heap concatenation string-concatenation

说我有String表达式

String hi = "Tom" + "Brady" + "Goat"

我知道字符串池"允许运行时通过保留池中的不可变字符串来节省内存。 String Pool

字符串池中将创建多少个字符串?

我的初步猜测是5 - "Tom""Brady""Goat""TomBrady""TomBradyGoat",因为{{1}的操作顺序连接(从左到右?)或者它只是最终结果," TomBradyGoat",它存储在字符串池中?

4 个答案:

答案 0 :(得分:5)

这里有一个常量表达式,由JLS, Section 15.28定义。

  

常量表达式是表示基本类型值的表达式或不突然完成的字符串,仅使用以下内容组成:

     
      
  • String类型的原始类型和文字的文字(§3.10.1,§3.10.2,§3.10.3,§3.10.4,§3.10.5)

  •   
  • 转换为基本类型并转换为String类型(第15.16节)

  •   
  • 一元运算符+, - ,〜和! (但不是++或 - )(§15.15.3,§15.15.4,§15.15.5,§15.15.6)

  •   
  • 乘法运算符*,/和%(§15.17)

  •   
  • 加法运算符+和 - (§15.18)

  •   

(其他可能性)

编译器确定表达式"Tom" + "Brady" + "Goat"是一个常量表达式,因此它将表达式本身计算为"TomBradyGoat"

JVM在字符串池中只有一个字符串"TomBradyGoat"

答案 1 :(得分:3)

在运行时,该段代码将转换为单个String对象。编译器将在编译时处理串联,并在常量池中添加单个值。

答案 2 :(得分:1)

其他答案解释了为什么只有1个字符串被添加到字符串池中。但是,如果您想自己检查并进行一些测试,可以查看字节码以查看创建并添加到字符串池的String数。例如:

练习1:

public static void main(String[] args) {
    String hi = "Tom" + "Brady" + "Goat";
}

字节代码:

  // access flags 0x9
  public static main(String[]) : void
   L0
    LINENUMBER 6 L0
    LDC "TomBradyGoat"
    ASTORE 1
   L1
    LINENUMBER 7 L1
    RETURN
   L2
    LOCALVARIABLE args String[] L0 L2 0
    LOCALVARIABLE hi String L1 L2 1
    MAXSTACK = 1
    MAXLOCALS = 2

正如您所看到的,只创建了1个字符串

练习2:

public static void main(String[] args) {
        String str1 = "Tom";
        String str2 = "Brady";
        String str3 = "Goat";
        String str = str1 + str2 + str3;
}

字节码:

  // access flags 0x9
  public static main(String[]) : void
   L0
    LINENUMBER 6 L0
    LDC "Tom"
    ASTORE 1
   L1
    LINENUMBER 7 L1
    LDC "Brady"
    ASTORE 2
   L2
    LINENUMBER 8 L2
    LDC "Goat"
    ASTORE 3
   L3
    LINENUMBER 9 L3
    NEW StringBuilder
    DUP
    ALOAD 1: str1
    INVOKESTATIC String.valueOf (Object) : String
    INVOKESPECIAL StringBuilder.<init> (String) : void
    ALOAD 2: str2
    INVOKEVIRTUAL StringBuilder.append (String) : StringBuilder
    ALOAD 3: str3
    INVOKEVIRTUAL StringBuilder.append (String) : StringBuilder
    INVOKEVIRTUAL StringBuilder.toString () : String
    ASTORE 4
   L4
    LINENUMBER 10 L4
    RETURN
   L5
    LOCALVARIABLE args String[] L0 L5 0
    LOCALVARIABLE str1 String L1 L5 1
    LOCALVARIABLE str2 String L2 L5 2
    LOCALVARIABLE str3 String L3 L5 3
    LOCALVARIABLE str String L4 L5 4
    MAXSTACK = 3
    MAXLOCALS = 5

如您所见,创建了4个字符串

答案 3 :(得分:-1)

正如其他人所提到的,编译器足以优化这个非常简单的示例,但是如果你有更复杂的功能(这可能是你关心的),它可能不会。例如:

String a = "Tom";
String b = "Brady";
String c = a;
c += b;

这将导致创建3个字符串。