用javap -c Test 在JDK5.0下,做实验。
实验一
String str = "a" + "b";
// 将字符串 ab 压入常数池
0: ldc #2; //String ab
编译器在编译时产生的字节码已经将 "a" + "b" 优化成了 "ab",
“字符串常量相加”的相加也会被优化处理。
实验二
String str = "a" + (1 + 2);
// 将字符串 a3 压入常数池
0: ldc #2; //String a3
虚拟机对其进行同样的优化。
常量间的相加并不会引起效率问题
试验三
String s = "b";
String str = "a" + s;
// 将字符串 b 压入常数池
0: ldc #2; //String b
// 将引用存放到 1 号局部变量中
2: astore_1
// 检查到非常量的相加,这时创建 StringBuilder 对象
3: new #3; //class java/lang/StringBuilder
// 从栈中复制出数据,即把字符串 b 复制出来
6: dup
// 调用 StringBuilder 的初始构造
7: invokespecial #4; //Method java/lang/StringBuilder." <init>":()V
// 将字符串 a 压入常数池
10: ldc #5; //String a
// 调用 StringBuilder 的 append 方法,把字符串 a 添加进去 (第一次append)
12: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
// 从 1 号局部变量中加载数据引用
15: aload_1
// 调用 StringBuilder 的 append 方法,把字符串 b 添加进去 (第二次append)
16: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
// 调用 StringBuilder 的 toString 方法
19: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
// 将 toString 的结果保存至 2 号局部变量
22: astore_2
23: return
变量中存放的是字符串的地址引用, 因为在编译时无法确定它具体的值,无法对其进行优化处理,
这时为了达到连接的效果,其内部采用了 StringBuilder 的机制进行处理
String str = "a" + s;等同于
String str = new StringBuilder().append("a").append(s).toString();
String str = "a" + s + "b";等同于
String str = new StringBuilder().append("a").append(s).append("b").toString();
string“+”降低效率是这种情况,for循环中会降低效率,@@@@@@@@@@@@@
return a + "hhhh-" + "aaaa- " + "bbbb-" + "cccc-";和
return a.append("hhhh-").append("aaaaa-").append("bbbbb-").append("ccccc-").toString();
效率上基本上没区别。
不相信权威教条传说。相信JVM。
String s1="abc";
for(int i=0;i<3;i++){s1=s1+"def";}
0: ldc #2; //String abc
7: if_icmpge 36
10: new #3; //class java/lang/StringBuilder
StringBuilder s1=new StringBuilder("abc");
for(int i=0;i<3;i++){s1=s1.append("def");}
0: new #2; //class java/lang/StringBuilder
4: ldc #3; //String abc
6: invokespecial #4; //Method java/lang/StringBuilder."<init>":(Ljava/lan
14: if_icmpge 30
JVM常见指令
Code:
0: iconst_0 //和for循环有关
1: istore_2
2: iload_2
3: iconst_3
4: if_icmpge 19 //和for循环有关,到第19行结束
7: aload_0
8: aload_1
9: invokevirtual #14; //Method java/lang/StringBtring;)Ljava/lang/StringBuilder;
12: pop
13: iinc 2, 1 //和for循环有关,计数器?第2,1行?
16: goto 2 //和for循环有关,跳转到第2行?
19: aload_0
20: invokevirtual #15; //Method java/lang/StringBg/String;
23: areturn