Mat*_*all 5 java string optimization
这个问题主要是纯粹的好奇心(并且杀了一段时间).为了具体起见,我正在特别询问Java.
如果我将字符串(任何字符串)与空字符串连接起来,在内存中会发生什么,例如:
String s = "any old string";
s += "";
Run Code Online (Sandbox Code Playgroud)
我知道之后,s的内容仍然是"任何旧字符串",因为空的ASCII字符串作为ASCII null存储在内存中(因为,至少在Java中,字符串总是以空字符结尾).但是我很想知道Java(编译器?VM?)是否执行了足够的优化来知道s将不会改变,并且它可以完全省略字节码中的那条指令,或者如果在编译和运行时发生了不同的事情.
Mic*_*ers 16
这是字节码时间!
class EmptyString {
public static void main(String[] args) {
String s = "any old string";
s += "";
}
}
Run Code Online (Sandbox Code Playgroud)
javap -c EmptyString:
Compiled from "EmptyString.java"
class EmptyString extends java.lang.Object{
EmptyString();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String any old string
2: astore_1
3: new #3; //class java/lang/StringBuilder
6: dup
7: invokespecial #4; //Method java/lang/StringBuilder."":()V
10: aload_1
11: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
14: ldc #6; //String
16: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_1
23: return
}
您可以看到,无论连接的是什么,+=都会导致StringBuilder创建,因此无法在运行时进行优化.
另一方面,如果将两个String文字放在同一个表达式中,它们将由编译器连接:
class EmptyString {
public static void main(String[] args) {
String s = "any old string" + "";
}
}
Run Code Online (Sandbox Code Playgroud)
javap -c EmptyString:
Compiled from "EmptyString.java"
class EmptyString extends java.lang.Object{
EmptyString();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String any old string
2: astore_1
3: return
}