1、从.class 文件看为什么 String 进行“+” 操作性能不如 StringBuilder 的 append()请看下面这段代码public class StringTest public static void main(String args) String result = “;for(int i=0;i“);System.out.println(“result =“+result);StringBuilder result1 = new StringBuilder();for(int i=0;i“);System.out.println(“result1 =“+result1);
2、那么为什么 String 会很慢呢?我们一直说 String 是不可变的类,因此它慢,其实还有更深层的原因。我们把编译后的 StringTest.class 文件拖到 eclipse 里,发现 / Compiled from StringTest.java (version 1.6 : 50.0, super bit)public class com.cy.test.StringTest / Method descriptor #6 ()V/ Stack: 1, Locals: 1public StringTest();0 aload_0 this1 invokespecial java.la
3、ng.Object() 84 returnLine numbers:pc: 0, line: 3Local variable table:pc: 0, pc: 5 local: this index: 0 type: com.cy.test.StringTest/ Method descriptor #15 (Ljava/lang/String;)V/ Stack: 4, Locals: 4public static void main(java.lang.String args);0 ldc 162 astore_1 result3 iconst_04 istore_2 i5 goto 30
4、8 new java.lang.StringBuilder 1811 dup12 aload_1 result13 invokestatic java.lang.String.valueOf(java.lang.Object) : java.lang.String 2016 invokespecial java.lang.StringBuilder(java.lang.String) 2619 iload_2 i20 invokevirtual java.lang.StringBuilder.append(int) : java.lang.StringBuilder 2923 invokevi
5、rtual java.lang.StringBuilder.toString() : java.lang.String 3326 astore_1 result27 iinc 2 1 i30 iload_2 i31 bipush 1033 if_icmplt 836 getstatic java.lang.System.out : java.io.PrintStream 3739 ldc “ 4341 invokevirtual java.io.PrintStream.println(java.lang.String) : void 4544 getstatic java.lang.Syste
6、m.out : java.io.PrintStream 3747 new java.lang.StringBuilder 1850 dup51 ldc 5053 invokespecial java.lang.StringBuilder(java.lang.String) 2656 aload_1 result57 invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder 5260 invokevirtual java.lang.StringBuilder.toString(
7、) : java.lang.String 3363 invokevirtual java.io.PrintStream.println(java.lang.String) : void 4566 new java.lang.StringBuilder 1869 dup70 invokespecial java.lang.StringBuilder() 5573 astore_2 result174 iconst_075 istore_3 i76 goto 8879 aload_2 result180 iload_3 i81 invokevirtual java.lang.StringBuild
8、er.append(int) : java.lang.StringBuilder 2984 pop85 iinc 3 1 i88 iload_3 i89 bipush 1091 if_icmplt 7994 getstatic java.lang.System.out : java.io.PrintStream 3797 ldc “ 4399 invokevirtual java.io.PrintStream.println(java.lang.String) : void 45102 getstatic java.lang.System.out : java.io.PrintStream 3
9、7105 new java.lang.StringBuilder 18108 dup109 ldc 56111 invokespecial java.lang.StringBuilder(java.lang.String) 26114 aload_2 result1115 invokevirtual java.lang.StringBuilder.append(java.lang.Object) : java.lang.StringBuilder 58118 invokevirtual java.lang.StringBuilder.toString() : java.lang.String
10、33121 invokevirtual java.io.PrintStream.println(java.lang.String) : void 45124 returnLine numbers:pc: 0, line: 7pc: 3, line: 8pc: 8, line: 9pc: 27, line: 8pc: 36, line: 12pc: 44, line: 13pc: 66, line: 15pc: 74, line: 16pc: 79, line: 17pc: 85, line: 16pc: 94, line: 20pc: 102, line: 21pc: 124, line: 2
11、4Local variable table:pc: 0, pc: 125 local: args index: 0 type: java.lang.Stringpc: 3, pc: 125 local: result index: 1 type: java.lang.Stringpc: 5, pc: 36 local: i index: 2 type: intpc: 74, pc: 125 local: result1 index: 2 type: java.lang.StringBuilderpc: 76, pc: 94 local: i index: 3 type: intStack ma
12、p table: number of frames 4pc: 8, append: java.lang.String, intpc: 30, samepc: 79, full, stack: , locals: java.lang.String, java.lang.String, java.lang.StringBuilder, intpc: 88, same大家学过汇编,当然我们以前学的是 x8086 的汇编语言,这是 java jvm 的汇编语言(我们不是一直说 java 被编译成 class,jvm 把 class 编译成特定的机器码,这样 class 相当于是jvm 的汇编语言) 。
13、我们虽然不是太懂,但是可以根据英语单词意思以及以往学过的汇编推出红色字体部分是他的循环部分,大概就是先 goto 跳转的判断语句 if_icmplt 8 判断符不符合条件(第 5 行,只得是它标注行数的地方,下面一样)符合就到 8 不符合往下走。iinc 2 1 i所给的 i 自增,这些都忽略。关键是蓝色字体的部分,你发现了区别,String 进行 + 操作产生了一个 StringBuilder 对象,这个对象进行 append() 。最后使用 toString()方法然后保存。并且这个对象实在循环内部,看上面的蓝色字体部位。这样你可以想象,屌丝们,循环十次会产生是个 StringBuilder 对象。调用十次 toString()方法。产生对象是非常耗性能的,亲。而使用 StringBuilder 时我们发现只产生了一个 StringBuilder 对象,他在循环体外产生。因此,他的开销小的多。所以大家现在明白了为什么 String 进行循环的字符串 + 操作会那么慢了吧?如果不是进行循环时间差不多的,因为只产生了一个 StringBuilder 而已,两个应该差不多。个人理解,不喜勿喷,欢迎那个纠错。