Java中到底有没有必要使用StringBuilder#append方法代替使用‘+’来拼接字符串

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gybshen/article/details/87920133

对具有一定编程经验的java开发者,在编码的时候遇到字符串拼接的情况,一般不会使用‘+’号来拼接,认为这样做效率低,使用StringBuilder的append方法取而代之。在这之前我也觉得这种观点是对的,并且深信不疑。

在Java中到底有没有必要使用StringBuilder#append方法代替‘+’来拼接字符串,在代码中使用‘+’号来拼接字符串真的会产生效率问题吗?

答案是否定的!

要想彻底弄清楚这个问题需要从本质出发,也就是从java编译过生成的字节码出发。

下面看一段简单的代码:

public class Test1 {
    public void test(){
        String a = "bbb";
        String str = "aaaa"+a+"cccc";
    }
}

使用‘+’ 来拼接三个字符串。使用javac编译这段代码,然后使用javap反编译生成的字节码

javap -v Test1.class

 反编译的结果如下:

Classfile /root/IdeaProjects/test/src/com/company/jvm/Test1.class
  Last modified 2019-2-25; size 456 bytes
  MD5 checksum dae3b157b314fcc38f820dc7788df354
  Compiled from "Test1.java"
public class com.company.jvm.Test1
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #10.#18        // java/lang/Object."<init>":()V
   #2 = String             #19            // bbb
   #3 = Class              #20            // java/lang/StringBuilder
   #4 = Methodref          #3.#18         // java/lang/StringBuilder."<init>":()V
   #5 = String             #21            // aaaa
   #6 = Methodref          #3.#22         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #7 = String             #23            // cccc
   #8 = Methodref          #3.#24         // java/lang/StringBuilder.toString:()Ljava/lang/String;
   #9 = Class              #25            // com/company/jvm/Test1
  #10 = Class              #26            // java/lang/Object
  #11 = Utf8               <init>
  #12 = Utf8               ()V
  #13 = Utf8               Code
  #14 = Utf8               LineNumberTable
  #15 = Utf8               test
  #16 = Utf8               SourceFile
  #17 = Utf8               Test1.java
  #18 = NameAndType        #11:#12        // "<init>":()V
  #19 = Utf8               bbb
  #20 = Utf8               java/lang/StringBuilder
  #21 = Utf8               aaaa
  #22 = NameAndType        #27:#28        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #23 = Utf8               cccc
  #24 = NameAndType        #29:#30        // toString:()Ljava/lang/String;
  #25 = Utf8               com/company/jvm/Test1
  #26 = Utf8               java/lang/Object
  #27 = Utf8               append
  #28 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #29 = Utf8               toString
  #30 = Utf8               ()Ljava/lang/String;
{
  public com.company.jvm.Test1();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 7: 0

  public void test();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: ldc           #2                  // String bbb
         2: astore_1
         3: new           #3                  // class java/lang/StringBuilder
         6: dup
         7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
        10: ldc           #5                  // String aaaa
        12: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        15: aload_1
        16: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        19: ldc           #7                  // String cccc
        21: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        24: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        27: astore_2
        28: return
      LineNumberTable:
        line 9: 0
        line 10: 3
        line 11: 28
}
SourceFile: "Test1.java"

从52行开始是test方法的操作指令,在59行可以明显的看出有new这个指令,这个指令是一个创建对象的指令,创建的对象就是StringBuilder的对象,再看63、65、67行invokevirtual指令代表调用StringBuilder对象的append方法,也就是使用append方法来拼接字符串,第68行调用StringBuilder的toString方法返回拼接的字符串。

综上:在源码中使用‘+’拼接字符串,在编译的时候编译器会自动优化我们的代码,使用StringBuilder的append方法来拼接字符串。所以我们在源码中大可放心的使用‘+’拼接字符串,不会产生效率问题!但是一般会增加额外的编译时间,造成编译效率的降低!也不必担心,因为这种影响是微乎其微的。

猜你喜欢

转载自blog.csdn.net/gybshen/article/details/87920133