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

说我有这个String表达式

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

我知道字符串池“允许运行时通过在池中保留不可变字符串来节省内存” 字符串池

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

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

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

你在这里得到的是一个常量表达式 ,如JLS第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个String被添加到String池中。 但是,如果您想自己检查并进行一些测试,可以查看字节码以查看创建并添加到字符串池的String数。 例如:

EX1:

 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个String

EX2:

 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. (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个字符串

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

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

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