+和StringBuilder的比较

  • Post author:
  • Post category:其他


这个东西说过的人太多了,其实也没有什么好再说的.我说的都是别人说过的.不过,别人说的始终是别人的,看过即忘,

java源码

package cn.jvm;

public class StringTest {
	public static void main(String[] args) {
		test1();
		test2();
	}

	public static void test1() {
		String a="single";
		String b="dog";
		String c=a+b;
		System.out.println(c);
	}

	public static void test2() {
		StringBuilder sb=new StringBuilder();
		String a="single";
		String b="dog";
		sb.append(a);
		sb.append(b);
		String c=sb.toString();
		System.out.println(c);
	}
}

jVM字节码

 public static void test1();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=3, args_size=0
         0: ldc           #24                 // String single          //将single从常量池中推送到栈顶
         2: astore_0                                                    //将栈顶数弹给变量0,a=single
         3: ldc           #26                 // String dog
         5: astore_1                                                    //b=dog
         6: new           #28                 // class java/lang/StringBuilder  //new一个StringBuilder对象,并将其压入栈顶
         9: dup                                                                  //复制栈顶数值并将复制值压入栈
        10: aload_0                                        //single入栈
        11: invokestatic  #30                 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
        14: invokespecial #36                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V   //初始化StringBuilder对象
        17: aload_1                                                      //dog入栈
        18: invokevirtual #39                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;  //使用StringBuilder的append方法拼接字符串
        21: invokevirtual #43                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; //StringBuilder转成String
        24: astore_2                           //将栈值弹给c   c=singledog
        25: getstatic     #47                 // Field java/lang/System.out:Ljava/io/PrintStream;
        28: aload_2
        29: invokevirtual #53                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        32: return
      LineNumberTable:
        line 10: 0
        line 11: 3
        line 12: 6
        line 13: 25
        line 14: 32
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            3      30     0     a   Ljava/lang/String;
            6      27     1     b   Ljava/lang/String;
           25       8     2     c   Ljava/lang/String;

  public static void test2();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=0
         0: new           #28                 // class java/lang/StringBuilder   //创建StringBuilder对象,并将其压入栈顶
         3: dup									//复制栈顶数值并将复制值压入栈
         4: invokespecial #62                 // Method java/lang/StringBuilder."<init>":()V//初始化StringBuilder对象
         7: astore_0                           //sb=new StringBuilder()
         8: ldc           #24                 // String single
        10: astore_1                                             //a=single
        11: ldc           #26                 // String dog
        13: astore_2                                           //b=dog;
        14: aload_0                                                            //sb对象入栈
        15: aload_1													//single入栈
        16: invokevirtual #39                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; //sb.append(single)
        19: pop                                              //从栈顶弹出
        20: aload_0
        21: aload_2
        22: invokevirtual #39                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;sb.append(dog)
        25: pop
        26: aload_0
        27: invokevirtual #43                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;  sb.toString
        30: astore_3                                                                                        //c=sb.toString
        31: getstatic     #47                 // Field java/lang/System.out:Ljava/io/PrintStream;
        34: aload_3
        35: invokevirtual #53                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        38: return
      LineNumberTable:
        line 17: 0
        line 18: 8
        line 19: 11
        line 20: 14
        line 21: 20
        line 22: 26
        line 23: 31
        line 24: 38
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            8      31     0    sb   Ljava/lang/StringBuilder;
           11      28     1     a   Ljava/lang/String;
           14      25     2     b   Ljava/lang/String;
           31       8     3     c   Ljava/lang/String;
}

从这个例子来看,a+b的底层,其实也是使用了StringBuilder的append()方法,由此来看,似乎两者差别不大.

java源码

package cn.jvm;

public class StringTest3 {
	public static void main(String[] args) {
		test1();
		test2();
	}

	public static void test1() {
		String a="work";
		String b="";
		for(int i=0;i<10;i++) {
			b+=a;
		}
		System.out.println(b);
	}

	public static void test2() {
		String a="work";
		StringBuilder sb=new StringBuilder();
		for(int i=0;i<10;i++) {
			sb.append(a);
		}
		String b=sb.toString();
		System.out.println(b);
	}
}

JVM字节码

 public static void test1();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=3, args_size=0
         0: ldc           #24                 // String work
         2: astore_0              //a=work;
         3: ldc           #26                 // String
         5: astore_1               //b="";
         6: iconst_0
         7: istore_2                //i=1
         8: goto          33        //去到第33  i入栈
		 -------------------循环开始-------------------
        11: new           #28                 // class java/lang/StringBuilder    //创建一个StringBuilder,这是在循环内创建
        14: dup
        15: aload_1
        16: invokestatic  #30                 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
        19: invokespecial #36                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
        22: aload_0
        23: invokevirtual #39                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        26: invokevirtual #43                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        29: astore_1
        30: iinc          2, 1
        33: iload_2                      //i入栈
        34: bipush        10              //10入栈
        36: if_icmplt     11            //如果i<10,去到第11
		/----------循环结束--------------------
        39: getstatic     #47                 // Field java/lang/System.out:Ljava/io/PrintStream;
        42: aload_1
        43: invokevirtual #53                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        46: return
      

  public static void test2();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=0
         0: ldc           #24                 // String work
         2: astore_0                         //a=work
         3: new           #28                 // class java/lang/StringBuilder   //创建一个StringBuilder,循环外创建
         6: dup
         7: invokespecial #64                 // Method java/lang/StringBuilder."<init>":()V
        10: astore_1						 //sb=new StringBuilder()
        11: iconst_0                          
        12: istore_2                 //i=0;
        13: goto          25       //调到第25
		/--------------------------循环开始-----------------
        16: aload_1          //sb入栈
        17: aload_0           //a入栈
        18: invokevirtual #39                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        21: pop
        22: iinc          2, 1
        25: iload_2                        //i入栈
        26: bipush        10              //10入栈
        28: if_icmplt     16                //如果i<10,调到第16
		//-----------------循环结束-------------------
        31: aload_1
        32: invokevirtual #43                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        35: astore_2
        36: getstatic     #47                 // Field java/lang/System.out:Ljava/io/PrintStream;
        39: aload_2
        40: invokevirtual #53                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        43: return

从上面的字节码中可以明显的看到,在test1()中,每次循环都会新建一个StringBuilder对象,而在test2中,只有一个StringBuilder对象.



版权声明:本文为bushanyantanzhe原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。