在编程中我们经常会使用到字符串拼接的方式,比如redis使用key的命名空间和key进行拼接,请求地址的url的拼接或者数据库多个返回字段的拼接等。那么我们
平时在使用“+”进行字符串拼接的时候,我们有想过编译器会对我们的程序进行何种处理吗?到底我们的程序会怎么执行呢?今天通过反汇编指令来看看拼接后代码是怎么个样子。
让我们看看最简单的拼接方式:
public static void main(String[] args) {
String a = "a";
String b = "b";
String c = a + b;
System.out.println(c);
}
通过下面的反汇编指令我们可以看到经过编译器编译后的jvm汇编代码。
javap -v class地址
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;
第一行是栈深,本地变量数,参数个数
0-5行:行是将字符串的值存储到对应的局部变量表a、b中;
6-10行:会初始化一个StringBuilder对象c;
14行:将调用c.append(a)
18行:再次调用c.append(b)
19行:调用toString方法返回String
24-25行:加载c到操作数栈,然后调用打印方法
所以 String c = a + b,翻译成我们平常的代码就是:
StringBuilder c = new StringBuilder();
c.append(a).append(b).toString();
我们在循环中为什么要避免使用“+”字符串拼接的方式,因为每次循环都会new一个新的StringBuilder对象,导致大量新的对象产生可能会导致OOM。