Java中关于StringBuilder和+号字符串拼接的效率问题

有这么一个例子:

String a = "nihao";
String b = "1233";
int c = 21;
String res = a+b+"dd"+c;

开始我就是这样写的,然后同时看到了跟我说最好用string builder,效率高一点,然后我感觉有道理,就改了:

StringBuilder builder = new StringBuilder();
builder.append("nihao").append("1233").append(21);

但是这个时候ide提醒我如下,就是让我该回去

Reports any usages of StringBuffer, StringBuilder or StringJoiner which can be replaced with a single java.lang.String concatenation. Using a String concatenation makes the code shorter and simpler. This inspection only reports when the resulting concatenation is at least as efficient or more efficient than the original code.

网上重新查了查,我就重新写了个测试,验证一下不同。
test1:

public void test1(){
        StringBuilder builder = new StringBuilder();
        builder.append("nihao").append("1233").append(21);
        System.out.println(builder.toString());
    }

编译后:

public void test1() {
        StringBuilder builder = new StringBuilder();
        builder.append("nihao").append("1233").append(21);
        System.out.println(builder.toString());
    }

用builder没有什么不同。
test2:

public void test2(){
        String a = "nihao";
        String b = "1233";
        int c = 21;
        String res = a+b+"dd"+c;
        String two = "dffe"+123+"ddd";
    }

编译后:

public void test2() {
        String a = "nihao";
        String b = "1233";
        int c = 21;
        (new StringBuilder()).append(a).append(b).append("dd").append(c).toString();
        String two = "dffe123ddd";
    }

这个时候不同就多了。看一下反编译结果(javap -c TestDemo.class):

  public void test1();
    Code:
       0: new           #2                  // class java/lang/StringBuilder
       3: dup
       4: invokespecial #3                  // Method java/lang/StringBuilder."":()V
       7: astore_1
       8: aload_1
       9: ldc           #4                  // String nihao
      11: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      14: ldc           #6                  // String 1233
      16: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: bipush        21
      21: invokevirtual #7                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      24: pop
      25: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      28: aload_1
      29: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      32: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      35: return

  public void test2();
    Code:
       0: ldc           #4                  // String nihao
       2: astore_1
       3: ldc           #6                  // String 1233
       5: astore_2
       6: bipush        21
       8: istore_3
       9: new           #2                  // class java/lang/StringBuilder
      12: dup
      13: invokespecial #3                  // Method java/lang/StringBuilder."":()V
      16: aload_1
      17: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      20: aload_2
      21: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      24: ldc           #11                 // String dd
      26: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      29: iload_3
      30: invokevirtual #7                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      33: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      36: astore        4
      38: ldc           #12                 // String dffe123ddd
      40: astore        5
      42: return

最后,再结合网上的其他测试,有以下几点:
1、如果+拼接的时候没有对象,比如String two = "dffe"+123+"ddd";,这种情况效率最高,不要画蛇添足的非要用string builder。你看编译后的结果,JVM直接就做了拼接转化,根本不用builder.
2、如果你要拼接的包含对象,比如String res = a+b+"dd"+c;,而且不用于循环,这个时候用+ 和 用builder 随意,都一样。
3、一行 + 操作就会产生一个builder(当然,分号结尾才是一行)。比如String res = a+b+"dd"+c; res += "555";会new 两次builder。这和用在循环一个道理,同样每次循环都会重新new一个builder。所以用在循环或者多行操作的时候,builder是效率最高的,次数少的话和buffer是差不多的。

你可能感兴趣的:(java笔记)