版权声明:本文为博主原创文章,未经博主允许不得转载。 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方法来拼接字符串。所以我们在源码中大可放心的使用‘+’拼接字符串,不会产生效率问题!但是一般会增加额外的编译时间,造成编译效率的降低!也不必担心,因为这种影响是微乎其微的。