首页 > 代码库 > StringBuilder的append、StringBuffer的append和String str = "a"+"b"的区别?

StringBuilder的append、StringBuffer的append和String str = "a"+"b"的区别?

大家都知道String+String会开销额外的系统资源,粗略的原因是String是不可变类,每一步操作都会返回新的String变量,占用空间及时间。
其实我的理解不是这样的,我们来看看String+的底层实现。

测试案例

public static void main(String[] args) {        String a = "a";        StringBuilder b = new StringBuilder("b");        StringBuffer c = new StringBuffer("c");        long star = System.currentTimeMillis();        for(int i=0;i<200000;i++){            a+="a";        }        long end = System.currentTimeMillis();        System.out.println("String:"+(end-star));                star = System.currentTimeMillis();        for(int i=0;i<200000;i++){            b.append("b");        }        end = System.currentTimeMillis();        System.out.println("StringBuilder:"+(end-star));                star = System.currentTimeMillis();        for(int i=0;i<200000;i++){            c.append("c");        }        end = System.currentTimeMillis();        System.out.println("StringBuffer:"+(end-star));    }

测试结果

String:17735
StringBuilder:6
StringBuffer:7

测试结论
String+ 确实占用了太多的资源,处理效率非常低下。StringBuilder比StringBuffer更新了同步方法,性能有所提升。
原因分析
我用javap -verbose 查看已经编译好的class文件发现:

public static void main(java.lang.String[]);   flags: ACC_PUBLIC, ACC_STATIC   Code:     stack=6, locals=9, args_size=1        0: ldc           #16                 // String a        2: astore_1        3: new           #18                 // class java/lang/StringBuilder        6: dup        7: ldc           #20                 // String b        9: invokespecial #22                 // Method java/lang/StringBuilder.<init>":(Ljava/lang/String;)V       12: astore_2       13: new           #25                 // class java/lang/StringBuffer       16: dup       17: ldc           #27                 // String c       19: invokespecial #29                 // Method java/lang/StringBuffer."init>":(Ljava/lang/String;)V       22: astore_3       23: invokestatic  #30                 // Method java/lang/System.currentimeMillis:()J       26: lstore        4       28: iconst_0       29: istore        6       31: goto          57       34: new           #18                 // class java/lang/StringBuilder       37: dup       38: aload_1       39: invokestatic  #36                 // Method java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;       42: invokespecial #22                 // Method java/lang/StringBuilder.<init>":(Ljava/lang/String;)V       45: ldc           #16                 // String a       47: invokevirtual #42                 // Method java/lang/StringBuilder.ppend:(Ljava/lang/String;)Ljava/lang/StringBuilder;       50: invokevirtual #46                 // Method java/lang/StringBuilder.oString:()Ljava/lang/String;       53: astore_1       54: iinc          6, 1       57: iload         6       59: ldc           #50                 // int 100000       61: if_icmplt     34       64: invokestatic  #30                 // Method java/lang/System.currentimeMillis:()J       67: lstore        6       69: getstatic     #51                 // Field java/lang/System.out:Ljav/io/PrintStream;       72: new           #18                 // class java/lang/StringBuilder       75: dup       76: ldc           #55                 // String String:       78: invokespecial #22                 // Method java/lang/StringBuilder.<init>":(Ljava/lang/String;)V       81: lload         6       83: lload         4       85: lsub       86: invokevirtual #57                 // Method java/lang/StringBuilder.ppend:(J)Ljava/lang/StringBuilder;       89: invokevirtual #46                 // Method java/lang/StringBuilder.oString:()Ljava/lang/String;       92: invokevirtual #60                 // Method java/io/PrintStream.prinln:(Ljava/lang/String;)V       95: invokestatic  #30                 // Method java/lang/System.currentimeMillis:()J       98: lstore        4      100: iconst_0      101: istore        8      103: goto          116      106: aload_2      107: ldc           #20                 // String b      109: invokevirtual #42                 // Method java/lang/StringBuilder.ppend:(Ljava/lang/String;)Ljava/lang/StringBuilder;      112: pop      113: iinc          8, 1      116: iload         8      118: ldc           #50                 // int 100000      120: if_icmplt     106      123: invokestatic  #30                 // Method java/lang/System.currentimeMillis:()J      126: lstore        6      128: getstatic     #51                 // Field java/lang/System.out:Ljav/io/PrintStream;      131: new           #18                 // class java/lang/StringBuilder      134: dup      135: ldc           #65                 // String StringBuilder:      137: invokespecial #22                 // Method java/lang/StringBuilder.<init>":(Ljava/lang/String;)V      140: lload         6      142: lload         4      144: lsub      145: invokevirtual #57                 // Method java/lang/StringBuilder.ppend:(J)Ljava/lang/StringBuilder;      148: invokevirtual #46                 // Method java/lang/StringBuilder.oString:()Ljava/lang/String;      151: invokevirtual #60                 // Method java/io/PrintStream.prinln:(Ljava/lang/String;)V      154: invokestatic  #30                 // Method java/lang/System.currentimeMillis:()J      157: lstore        4      159: iconst_0      160: istore        8      162: goto          175      165: aload_3      166: ldc           #27                 // String c      168: invokevirtual #67                 // Method java/lang/StringBuffer.apend:(Ljava/lang/String;)Ljava/lang/StringBuffer;      171: pop      172: iinc          8, 1      175: iload         8      177: ldc           #50                 // int 100000      179: if_icmplt     165      182: invokestatic  #30                 // Method java/lang/System.currentimeMillis:()J      185: lstore        6      187: getstatic     #51                 // Field java/lang/System.out:Ljav/io/PrintStream;      190: new           #18                 // class java/lang/StringBuilder      193: dup      194: ldc           #70                 // String StringBuffer:      196: invokespecial #22                 // Method java/lang/StringBuilder.<init>":(Ljava/lang/String;)V      199: lload         6      201: lload         4      203: lsub      204: invokevirtual #57                 // Method java/lang/StringBuilder.ppend:(J)Ljava/lang/StringBuilder;      207: invokevirtual #46                 // Method java/lang/StringBuilder.oString:()Ljava/lang/String;      210: invokevirtual #60                 // Method java/io/PrintStream.prinln:(Ljava/lang/String;)V      213: return

从编译的代码来看,String+的准确操作是:
new StringBuilder()
new String.valueof()
StringBuilder.<init>
StringBuilder.append()
StringBuilder.toString()
而StringBuilder的准确操作是:
StringBuilder.append()
而StringBuffer()的准确操作是:
StringBuffer.append

 

转自http://alqm1314-126-com.iteye.com/blog/1932879

StringBuilder的append、StringBuffer的append和String str = "a"+"b"的区别?