源代码:
public class Test{
public static void main(String[]args){
String x = "";
for(int i=0;i<10;i++){
x+="abc";
}
System.out.println(x);
}
}
javap:反编译结果
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String --ldc:常数到操作数栈 ""
2: astore_1 --astore:将引用类型或returnAddress类型值存入局部变量 String x = ""
3: iconst_0 --iconst_0:将int类型常量0压入栈
4: istore_2 --istore:将int类型值存入局部变量 int i = 0
5: iload_2 --iload:从局部变量装载int类型值 取出i
6: bipush 10 --bipush:将一个8位带符号整数压入栈 压入10
8: if_icmpge 37 --if_icmpge:如果一个int类型值大于或者等于另外一个int类型值,则跳转 执行i<10判断
11: new #3; //class java/lang/StringBuilder
14: dup
15: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
18: aload_1 --aload:从局部变量装载引用型数据 取出String x("");
19: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/String
22: ldc #6; //String abc
24: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/String
27: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
30: astore_1 --astore:将引用类型或returnAddress类型值存入局部变量 将toString结果赋值给x
31: iinc 2, 1 --iinc:将一个常量值加到一个int类型的局部变量上 i+1
34: goto 5
37: getstatic #8; //Field java/lang/System.out:Ljava/io/PrintStream;
40: aload_1
41: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
44: return
对照程序可以更好的理解反编译命令,留作以后参考。
可以看到:jvm对于String+String操作符做了优化,通过StringBuilder.append方法来执行+操作,缺点如上所示,在循环执行+操作时,每次都会创建一个新的StringBuilder。