String是面试经常被问及的小知识点,它扩展开来还是有很多好玩的东西,下边就从编译层面上仔细分析一下
代码1:
public class Test { public static void main(String[] args) { String str1 = "a"; String str2 = "b"; String str3 = str1 + str2; System.out.println(str3); } }
编译后:
{ public com.test.mvn.Test(); flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 6: 0 public static void main(java.lang.String[]); flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 0: ldc #2 // String a 2: astore_1 3: ldc #3 // String b 5: astore_2 6: new #4 // class java/lang/StringBuilder 9: dup 10: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V 13: aload_1 14: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 17: aload_2 18: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 21: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 24: astore_3 25: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 28: aload_3 29: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 32: return LineNumberTable: line 8: 0 line 9: 3 line 10: 6 line 11: 25 line 12: 32 }
解析:
0: ldc #2 常量池中的常量值入栈 2: astore_1 将栈顶引用类型值保存到局部变量1中。 3: ldc #3 常量池中的常量值入栈 5: astore_2 将栈顶引用类型值保存到局部变量2中 6: new #4 新建StringBuilder对象 9: dup 复制栈顶一个字长的数据,将复制后的数据压栈 10: invokespecial #5 编译时方法绑定调用方法 13: aload_1 从局部变量1中装载引用类型值入栈 14: invokevirtual #6 运行时方法绑定调用方法 17: aload_2 从局部变量2中装载引用类型值入栈 18: invokevirtual #6 运行时方法绑定调用方法 21: invokevirtual #7 运行时方法绑定调用方法 24: astore_3 将栈顶引用类型值保存到局部变量3中 25: getstatic #8 获取静态字段的值 28: aload_3 从局部变量3中装载引用类型值入栈 29: invokevirtual #9 运行时方法绑定调用方法 32: return void函数返回