首先说明:
至于是StringBuilder还是StringBuffer去取代“+”,这就是实际应用场景需要考量的,看你的应用场景需要考虑线程安全性与否!
每个观点的提出都要有理有据:
如下是两段字符串拼接两种实现方式:
public class TestA { public static void main(String[] args) { String str = "A" ; StringBuilder sb = new StringBuilder(str) ; sb.append("B"); sb.append("C"); System.out.println(str); } }
第二段:
public class TestB { public static void main(String[] args) { String str = "A" ; str += "B" ; str += "C" ; System.out.println(str); } }
然后用javap去分析:
TestA的分析结果:
public static void main(java.lang.String[]); Code: 0: ldc #2; //String A 2: astore_1 3: new #3; //class java/lang/StringBuilder 6: dup 7: aload_1 8: invokespecial #4; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V 11: astore_2 12: aload_2 13: ldc #5; //String B 15: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/S tringBuilder; 18: pop 19: aload_2 20: ldc #7; //String C 22: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/S tringBuilder; 25: pop 26: getstatic #8; //Field java/lang/System.out:Ljava/io/PrintStream; 29: aload_1 30: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 33: return }
TestB的分析结果:
public static void main(java.lang.String[]); Code: 0: ldc #2; //String A 2: astore_1 3: new #3; //class java/lang/StringBuilder 6: dup 7: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V 10: aload_1 11: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/S tringBuilder; 14: ldc #6; //String B 16: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/S tringBuilder; 19: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 22: astore_1 23: new #3; //class java/lang/StringBuilder 26: dup 27: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V 30: aload_1 31: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/S tringBuilder; 34: ldc #8; //String C 36: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/S tringBuilder; 39: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 42: astore_1 43: new #3; //class java/lang/StringBuilder 46: dup 47: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V 50: aload_1 51: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/S tringBuilder; 54: ldc #9; //String D 56: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/S tringBuilder; 59: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 62: astore_1 63: getstatic #10; //Field java/lang/System.out:Ljava/io/PrintStream; 66: aload_1 67: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 70: return }
TestA只在第3行产生了1个StringBuilder对象,而TestB在第3,23,43产生了3个StringBuilder对象;
不论是从执行步骤复杂程度还是从StringBuilder实例化对象数量来讲,使用StringBuilder的效率明显高于使用“+”拼接字符串 。使用“+”拼接字符串JVM会将其转换为StringBuilder,但是每“+”一次,就是多一个StringBuilder对象,但是使用StringBuilder拼接字符串,只会有一个StringBuilder对象,另外注意,当使用StringBuilder拼接字符串个数大于它的容量capacity(默认是16)时,它会进行扩容,所以,在能够能够确定最大拼接数的情况下,在new StringBuilder()时,指定capacity-- StringBuilder sb = new StringBuilder(str,3) ;,可以进一步减少空间占用,提高性能!