String类"+"加号验证, 跟踪模式
?
用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