在内存中创建了多少个字符串?
How many Strings are created in memory?
假设我有这个 String
表达式
String hi = "Tom" + "Brady" + "Goat"
我知道字符串池"allows a runtime to save memory by preserving immutable strings in a pool"String Pool
字符串池中将创建多少个字符串?
我最初的猜测是 5 - "Tom"
、"Brady"
、"Goat"
、"TomBrady"
、"TomBradyGoat"
,因为 [=] 的运算顺序11=] 串联(从左到右?)还是仅存储在字符串池中的最终结果 "TomBradyGoat"?
在运行时,该段代码将转换为单个 String
对象。编译器将在编译时处理连接并在常量池中添加单个值。
这里是 常量表达式,由 JLS, Section 15.28.
定义
A constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:
Literals of primitive type and literals of type String (§3.10.1, §3.10.2, §3.10.3, §3.10.4, §3.10.5)
Casts to primitive types and casts to type String (§15.16)
The unary operators +, -, ~, and ! (but not ++ or --) (§15.15.3, §15.15.4, §15.15.5, §15.15.6)
The multiplicative operators *, /, and % (§15.17)
The additive operators + and - (§15.18)
(其他可能性)
编译器确定表达式 "Tom" + "Brady" + "Goat"
是常量表达式,因此它将表达式本身计算为 "TomBradyGoat"
.
JVM 将在字符串池中只有一个字符串,"TomBradyGoat"
。
正如其他人所提到的,编译器足以优化这个非常简单的示例,但如果您有更复杂的功能(这可能是您关心的),它可能不会。例如:
String a = "Tom";
String b = "Brady";
String c = a;
c += b;
这将导致创建 3 个字符串。
其他答案很好地解释了为什么只有 1 个字符串被添加到字符串池中。但是如果你想自己检查和做一些测试,你可以看一下字节码,看看创建和添加到字符串池中的字符串的数量。例如:
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 个字符串
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.<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 个字符串
假设我有这个 String
表达式
String hi = "Tom" + "Brady" + "Goat"
我知道字符串池"allows a runtime to save memory by preserving immutable strings in a pool"String Pool
字符串池中将创建多少个字符串?
我最初的猜测是 5 - "Tom"
、"Brady"
、"Goat"
、"TomBrady"
、"TomBradyGoat"
,因为 [=] 的运算顺序11=] 串联(从左到右?)还是仅存储在字符串池中的最终结果 "TomBradyGoat"?
在运行时,该段代码将转换为单个 String
对象。编译器将在编译时处理连接并在常量池中添加单个值。
这里是 常量表达式,由 JLS, Section 15.28.
定义A constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:
Literals of primitive type and literals of type String (§3.10.1, §3.10.2, §3.10.3, §3.10.4, §3.10.5)
Casts to primitive types and casts to type String (§15.16)
The unary operators +, -, ~, and ! (but not ++ or --) (§15.15.3, §15.15.4, §15.15.5, §15.15.6)
The multiplicative operators *, /, and % (§15.17)
The additive operators + and - (§15.18)
(其他可能性)
编译器确定表达式 "Tom" + "Brady" + "Goat"
是常量表达式,因此它将表达式本身计算为 "TomBradyGoat"
.
JVM 将在字符串池中只有一个字符串,"TomBradyGoat"
。
正如其他人所提到的,编译器足以优化这个非常简单的示例,但如果您有更复杂的功能(这可能是您关心的),它可能不会。例如:
String a = "Tom";
String b = "Brady";
String c = a;
c += b;
这将导致创建 3 个字符串。
其他答案很好地解释了为什么只有 1 个字符串被添加到字符串池中。但是如果你想自己检查和做一些测试,你可以看一下字节码,看看创建和添加到字符串池中的字符串的数量。例如:
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 个字符串
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.<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 个字符串