为什么要使用StringBuilder或者StringBuffer类

 在实际开发中,我们常被告知字符串的连接处理,一定要使用StringBuilder或者StringBuffer类,这是为什么呢?

这样可以提高效率,节省资源。

具体请看下面的例子:

public class StringTest {
    public static void main(String[] args) {

        // 无变量的字符串拼接
      String s = "aa"+"bb"+"dd";
        System.out.println(s);
        // 有变量的字符串拼接
        String g = "11"+s+5;
        System.out.println(g);
        // 循环中使用字符串拼接
        String a = "0";
        for (int i = 1; i < 10; i++) {
            a = a + i;
        }
        System.out.println(a);
        // 循环外定义StringBuilder
        StringBuilder b = new StringBuilder();
        for (int i = 1; i < 10; i++) {
            b.append(i);
        }
        System.out.println(b);
    }
}

用 Jdk 1.6 - 1.8 自带的 javap 工具进行了反编译,发现生成的 JVM 指令:

// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) annotate 
// Source File Name:   StringTest.java

import java.io.PrintStream;

public class StringTest
{

    public StringTest()
    {
    //    0    0:aload_0         
    //    1    1:invokespecial   #1   <Method void Object()>
    //    2    4:return          
    }

    public static void main(String args[])
    {
        String s = "aabbdd";
    //    0    0:ldc1            #2   <String "aabbdd">
    //    1    2:astore_1        
        System.out.println(s);
    //    2    3:getstatic       #3   <Field PrintStream System.out>
    //    3    6:aload_1         
    //    4    7:invokevirtual   #4   <Method void PrintStream.println(String)>
        String g = (new StringBuilder()).append("11").append(s).append(5).toString();
    //    5   10:new             #5   <Class StringBuilder>
    //    6   13:dup             
    //    7   14:invokespecial   #6   <Method void StringBuilder()>
    //    8   17:ldc1            #7   <String "11">
    //    9   19:invokevirtual   #8   <Method StringBuilder StringBuilder.append(String)>
    //   10   22:aload_1         
    //   11   23:invokevirtual   #8   <Method StringBuilder StringBuilder.append(String)>
    //   12   26:iconst_5        
    //   13   27:invokevirtual   #9   <Method StringBuilder StringBuilder.append(int)>
    //   14   30:invokevirtual   #10  <Method String StringBuilder.toString()>
    //   15   33:astore_2        
        System.out.println(g);
    //   16   34:getstatic       #3   <Field PrintStream System.out>
    //   17   37:aload_2         
    //   18   38:invokevirtual   #4   <Method void PrintStream.println(String)>
        String a = "0";
    //   19   41:ldc1            #11  <String "0">
    //   20   43:astore_3        
        for(int i = 1; i < 10; i++)
    //*  21   44:iconst_1        
    //*  22   45:istore          4
    //*  23   47:iload           4
    //*  24   49:bipush          10
    //*  25   51:icmpge          80
            a = (new StringBuilder()).append(a).append(i).toString();
    //   26   54:new             #5   <Class StringBuilder>
    //   27   57:dup             
    //   28   58:invokespecial   #6   <Method void StringBuilder()>
    //   29   61:aload_3         
    //   30   62:invokevirtual   #8   <Method StringBuilder StringBuilder.append(String)>
    //   31   65:iload           4
    //   32   67:invokevirtual   #9   <Method StringBuilder StringBuilder.append(int)>
    //   33   70:invokevirtual   #10  <Method String StringBuilder.toString()>
    //   34   73:astore_3        

    //   35   74:iinc            4  1
    //*  36   77:goto            47
        System.out.println(a);
    //   37   80:getstatic       #3   <Field PrintStream System.out>
    //   38   83:aload_3         
    //   39   84:invokevirtual   #4   <Method void PrintStream.println(String)>
        StringBuilder b = new StringBuilder();
    //   40   87:new             #5   <Class StringBuilder>
    //   41   90:dup             
    //   42   91:invokespecial   #6   <Method void StringBuilder()>
    //   43   94:astore          4
        for(int i = 1; i < 10; i++)
    //*  44   96:iconst_1        
    //*  45   97:istore          5
    //*  46   99:iload           5
    //*  47  101:bipush          10
    //*  48  103:icmpge          120
            b.append(i);
    //   49  106:aload           4
    //   50  108:iload           5
    //   51  110:invokevirtual   #9   <Method StringBuilder StringBuilder.append(int)>
    //   52  113:pop             

    //   53  114:iinc            5  1
    //*  54  117:goto            99
        System.out.println(b);
    //   55  120:getstatic       #3   <Field PrintStream System.out>
    //   56  123:aload           4
    //   57  125:invokevirtual   #12  <Method void PrintStream.println(Object)>
    //   58  128:return          
    }
}

1、无变量的字符串拼接,在编译期间值都确定了,所以 javac 工具帮我们把它直接编译成一个字符常量。

2、有变量的字符串拼接,在编译期间变量的值无法确定,所以运行期间会生成一个StringBuilder 对象。

3、循环中使用字符串拼接,循环内,每循环一次就会产生一个新的 StringBuilder 对象,对资源有一定的损耗。

4、循环外使用 StringBuilder,循环内再执行 append() 方法拼接字符串,只会成一个 StringBuilder 对象。

因此,对于有循环的字符串拼接操作,建议使用 StringBuilder 和 StringBuffer,对性能会有一定的提升。
--------------------- 
作者:Java面试那些事儿 
来源:CSDN 
原文:https://blog.csdn.net/wik_123/article/details/86484928 

猜你喜欢

转载自blog.csdn.net/qq_36528311/article/details/87871659