字符串拼接【面试题】

先来看一段代码

public class Test {
public String method1() {
        String ret = "";
        for(int i=0;i<100000;i++){
            ret=ret+"ok";
        }
return ret;
    }
public String method2() {
        StringBuilder ret = new StringBuilder("");
        for(int i=0;i<100000;i++){
            ret.append("ok");
        }
return ret.toString();
    }
}

都知道method1的性能会比method2的性能差。

那么理由是什么理由呢?

下面咱们来证明一下:

先编译代码,然后找到Test.class文件,然后执行命令

javap -verbose Test.class >tt.txt

然后打开tt.txt

public java.lang.String method1();
  descriptor: ()Ljava/lang/String;
  flags: ACC_PUBLIC
  Code:
    stack=2, locals=3, args_size=1
       0: ldc           #2                  // String
       2: astore_1
       3: iconst_0
       4: istore_2
       5: iload_2
       6: sipush        1000
       9: if_icmpge     38 //for循环
      12: new           #3 创建一个StringBuilder对象// class java/lang/StringBuilder
      15: dup
      16: invokespecial #4  // Method java/lang/StringBuilder."<init>":()V
      19: aload_1
      20: invokevirtual #5  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      23: ldc           #6   // String ok
      25: invokevirtual #5   // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      28: invokevirtual #7   // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      31: astore_1
      32: iinc          2, 1
      35: goto          5
      38: aload_1
      39: areturn

可以看出每次循环一次就new一个对象。

再来看看method2

public java.lang.String method2();
  descriptor: ()Ljava/lang/String;
  flags: ACC_PUBLIC
  Code:
    stack=3, locals=3, args_size=1
       0: new  #3 创建一个StringBuilder对象// class java/lang/StringBuilder
       3: dup
       4: ldc           #2                  // String
       6: invokespecial #8                  // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
       9: astore_1
      10: iconst_0
      11: istore_2
      12: iload_2
      13: sipush        1000
      16: if_icmpge     32 //循环
      19: aload_1
      20: ldc           #6                  // String ok
      22: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      25: pop
      26: iinc          2, 1
      29: goto          12
      32: aload_1
      33: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      36: areturn
    LineNumberTable:

有上面看出method2值创建了一个StringBuilder对象。

method1要创建n多个对象,而method2只需要创建一个对象,明显method2方式效率更高,推荐使用method2(StringBuilder)方式

但是如果在多线程环境下使用的话,推荐StringBuffer,因为StringBuffer是线程安全的。


上一篇:Lambda 表达式介绍和底层实现分析


下一篇:Android属性之build.prop生成过程分析