深入java String拼接和StringBuffer、StringBuilder(分析源码)

来源:互联网 发布:windows phone 知乎 编辑:程序博客网 时间:2024/04/19 16:39

上一篇文章我们查看了《阿里巴巴Java开发手册》(四.OOP规则)第17条对String有进行说明,看了String的源码,也从内存的角度分析了字符串的拼接。这一篇文章接着上一篇的内容,分析String在连接的时候发生的内容、StringBuffer和StringBuilder的用法和源码。原创不易,转载请注明出处:http://blog.csdn.net/yabay2208

  • 阿里巴巴的文档规范(上一篇)
  • String使用以及源码分析(上一篇)
  • String到底相等吗(上一篇)
  • String在重载运算符“+”的时候到底发生了什么
  • StringBuffer使用以及源代码分析
  • StringBuilder使用以及源代码分析
  • 这三种如何选择

四:String在重载运算符“+”的时候到底发生了什么

当我们在将String进行连接的时候,其实是通过append进行的操作:(举例说明)

String all = "hello"+"world"+"!"; String a  =  "hello";String b  =  "world";String c  =  "!";String tmp = a + b + c;

分析:变量all的创建等价于 String all = “”helloworld!”; 由上面例子可知编译器进行了优化,这里只创建了一个对象。通过之前的例子可以知道tmp不能在编译期进行优化,其对象创建相当于:

StringBuffer temp = new StringBuffer();temp.append(a).append(b).append(c);String tmp = temp.toString();

所以我们现在就明白了String(不可变类final)的拼接原理。


阿里巴巴的开发手册里面说到:
这里写图片描述
就相当于:
这里写图片描述
每做一次 “+” 就相当于就产生个StringBuilder对象,然后append后就扔掉。下次循环再到达时重新产生个StringBuilder对象,然后append 字符串,如此循环直至结束。如果我们直接采用StringBuilder对象进行append的话,我们可以节省N - 1次创建和销毁对象的时间。所以对于在循环中要进行字符串连接的应用,一般都是用StringBuffer或StringBulider对象来进行append操作。效率是很低下的。

五:StringBuffer使用以及源代码分析

StringBuffer是线程安全的,我们看一张图片就知道了:
这里写图片描述
StringBuffer除了构造函数没有用synchronized标注为同步方法之外,其他的方法都是同步的。

六:StringBuilder使用以及源代码分析

StringBuilder是非线程安全的,他跟StringBuffer的源代码基本上一莫一样,只是在StringBuffer标注了synchronized的同步方法这里都没有标注。
这里写图片描述

七:String、StringBuffer和StringBuilder的选择

第一:如果要操作少量的数据,用String(简单,代码易读) ;单线程操作大量数据,用StringBuilder(不考虑同步,速度很快) ;多线程操作大量数据,用StringBuffer(速度慢一点,安全)。

第二:不使用String类的”+”来进行频繁的拼接,因为性能极差,应该使用StringBuffer或StringBuilder类,这在Java的优化上是一条比较重要的原则。

第三: StringBuilder一般使用在方法内部来完成类似”+”功能,因为是线程不安全的,所以用完以后可以丢弃,同时,不考虑到线程的同步,速度很快。StringBuffer主要用在全局变量中,所有对象都能够访问到这一个变量,一定要考虑到线程的同步问题。

第四:相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。而在现实的模块化编程中,负责某一模块的程序员不一定能清晰地判断该模块是否会放入多线程的环境中运行,因此:除非确定系统的瓶颈是在 StringBuffer 上,并且确定你的模块不会运行在多线程模式下,才可以采用StringBuilder;否则还是用线程安全的StringBuffer。

1 0
原创粉丝点击