拼接字符串,用 “+” 还是StringBuilder.append()
  4cUZdr0QxHGA 2023年11月02日 37 0



文章目录

  • 倡议
  • “+”语法糖操作的本质
  • String、StringBuilder、StringBuffer性能比较
  • 一个特殊的例子
  • 总结


倡议

在《阿里java开发手册》中,对于Java字符串的拼接有一条规则如下:

  • 22.【推荐】循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。

“+”语法糖操作的本质

语法糖:语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·兰丁发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能没有影响,但是更方便程序员使用。语法糖让程序更加简洁,有更高的可读性。

“+”号操作符必须是字符串拼接最常用的一种了,没有之一。使用“+”拼接字符串,其实只是Java提供的一个语法糖。那么,我们就来解一解这个语法糖,看看他的内部原理到底是如何实现的。

还是这样一段代码。我们把他生成的字节码进行反编译,看看结果。

String str1= "唐伯虎";
 
String str2= "点香烟";
 
String endStr = str1+ "," + str2;

Dos反编译后的内容如下(反编译class文件的命令:javap -c 类名)。

String str1= "\u5510\u4f2f\u864e"; //唐伯虎
 
String str2= "\u70b9\u9999\u70df"; //点香烟
 
String endStr = (new StringBuilder()).append(str1).append(",").append(str2).toString();

通过查看反编译以后的代码,我们可以发现,原来字符串常量在拼接过程中,是将String转成了StringBuilder后,使用其append方法进行处理的。

那么也就是说,Java中的“+”对字符串的拼接,其实现原理是使用StringBuilder.append()方法。

String、StringBuilder、StringBuffer性能比较

三者在执行速度方面的比较:StringBuilder > StringBuffer > String 。原因:

  • String:字符串常量
  • StringBuffer:字符串变量(有同步锁)
  • StringBuilder:字符串变量(无同步锁)

具体分析下String:从上面的名字可以看到,String是"字符串常量",也就是不可改变的对象。源码如下:

public final class String{}

对于上面这句话的理解你可能会产生这样一个疑问 ,比如这段代码:

String str = "唐伯虎";
 
str = str + "点香烟";
 
System.out.print(str); // result : "唐伯虎点香烟"

我们明明改变了String型的变量str啊,为什么说是没有改变呢?我们来看一下这张对String操作时内存变化的图:

拼接字符串,用 “+” 还是StringBuilder.append()_Java

我们可以看到,初始String值为"唐伯虎",然后在这个字符串后面加上新的字符串"点香烟",这个过程是需要重新在栈堆内存中开辟内存空间的,最终得到了"唐伯虎点香烟"字符串也相应的需要开辟内存空间,这样短短的两个字符串,却需要开辟三次内存空间,不得不说这是对内存空间的极大浪费。

而,对于StringBuilder、StringBuffer,他们俩均属于字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在一个对象上操作的,这样就不会像String一样创建一些而外的对象进行操作了,速度自然就相对快了。
至于StringBuilder非线程安全、StringBuffer线程安全,这一点大家应该都清楚,StringBuffer的很多方法都被关键字synchronized 修饰了,而StringBuilder没有。

一个特殊的例子

String str = "This is only a" + " simple" + " test";
 
StringBuffer builder = new StringBuilder("This is only a").append(" simple").append(" test");

这段代码,经测试发现,生成str对象的速度远高于builder,而这个时候StringBuilder居然速度上根本一点都不占优势。为什么呢?

其实这是JVM的一个把戏,实际上:

String str = “This is” + " a " + “demo”; 等同于 String str = “This is a demo”;

这是因为,在JVM优化时,如果是多个固定字符串拼接,会将这些固定字符串进行预处理,当成一个整体的字符串,相当于仅声明一个常量,所以并不需要太多的时间。

但大家这里要注意的是,如果字符串拼接的多个元素中有其他String对象的话,速度就没那么快了,譬如:

String str = "唐伯虎";
 
str = str + "点香烟";

或者:

String str5 = "啦啦啦";
 
String str6 = str5 + "嘻嘻嘻";

这时候JVM会规规矩矩的按照原来的方式去做。

总结

  1. 如果不是在循环体中进行字符串拼接的话,直接使用 String 的 “+” 就好了。
  2. 单线程循环中操作大量字符串数据 → StringBuilder.append()
  3. 多线程循环中操作大量字符串数据 → StringBuffer.append()


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
4cUZdr0QxHGA
最新推荐 更多

2024-05-17