天天看點

居然還有人對字元串拼接操作時StringBuilder/StringBuffer取代“+”有疑問

首先說明:

至于是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) ;,可以進一步減少空間占用,提高性能!