String的拼接字符串,也许没有想象中那么简单


老生常谈的一句话 “StringBuilder在拼接字符串时效率更高”。

所以笔者写了如下测试代码

 1 public static void main(String[] args) {
 2     String s1 = "Hello";
 3     String s2 = "World";
 4     long st = System.currentTimeMillis();
 5     for (int i = 0; i < 100000; i++) {
 6         s1+=s2;
 7     }
 8     long en = System.currentTimeMillis();
 9     System.out.println(en-st);
10     
11     StringBuffer sb1 = new StringBuffer("Hello");
12     String sb2 = "World";
13     long st1 = System.currentTimeMillis();
14     for (int i = 0; i < 100000; i++) {
15         sb1.append(sb2);
16     }
17     long en1 = System.currentTimeMillis();
18     System.out.println(en1-st1);
19     
20 }

结果显示,时间相差了几千倍之多

32702
11

心中一丝困惑潜滋暗长,几十秒的差距,时间损耗在哪里呢?

在《java程序员面试宝典》这本书中,我找到如下这段话 

所以由此可见,时间损耗在了循环中 底层新建 StringBuffer对象的过程中。但笔者再次发现,有的博文中说 底层用的是StringBuilder。

于是我在查阅资料的过程中发现了“反编译”这一操作

(用编译好的字节码文件)执行如下操作

javap -v Demo.class

得到一串反编译后的代码(截取部分)

5:  new            #3                 // class java/lang/StringBuilder
8:  dup
9:  invokespecial  #4                 // Method java/lang/StringBuilder."<init>":()V
12: aload_1
13: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
16: aload_2
17: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
20: invokevirtual #6                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
23: astore_1
24: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
27: aload_1
28: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V

所以 可以确定,至少在此段代码所在版本(jdk1.8),底层调用的是StringBuilder的append()方法

经过再次查证

得出了阶段性的结论

String拼接字符串操作,底层新建了StringBuffer对象,并调用了它的append()方法 和toString()方法

在jdk1.5之后,将其更新成了StringBuilder进行此操作。

所以如果遇到了大量字符串拼接的场景,可以手动创建StringBuilder的临时对象,会显著节省时间。

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM