关于 String,StringBuilder,StringBuffer 的讨论,已有很多文章;在这里,做一些自己的整理。

  • String

   String 是final类型,不可继承的类;内部存储是字符数组(char[]),也是final ,不可更改;

  1. /** 源码中 String 类的声明 */
  2. public final class String
  3. implements java.io.Serializable, Comparable<String>, CharSequence {
  4. /** The value is used for character storage. */
  5. private final char value[];

  我们知道 final 修饰变量,只能被赋值一次,赋值成功后,不可再重新赋值。这意味怎么什么呢?先看一下下面的例子:

  1. public static void main(String[] args) {
  2. String a = "sdfsdklfjdskl1245";
  3. String b = "1234567489123";
  4. String c = a + b;
  5. System.out.println(c);
  6. }

  这里声明三个字符常量,在初始化时,a  和 b 是字符数组常量,而 c 则是两个常量字符的连接;下面是反编译后的信息:

根据描述信息,c 变量是两个字符串连接的副本。(小弟知识范围有限,若上述代码解读有误,还请指正,不胜感激)

  如果字符串直接拼接,又是怎样呢?

  1. public static void main(String[] args) {
  2. String a = "this is a" + " simple " + "test";
  3. System.out.println(a);
  4. }

  看看编译后的代码解析:

  

  可以看到编译过程做了优化,这里只产生了一个变量。

  所以 String 字符串的拼接,关键在于字符串连接底层实现方式;字符串的实现是不可变字符数组,那拼接又是对字符数组怎样的操作呢?是数组拷贝?还是其他方式,有待考究... ...

  String 字符串拼接效率低体现在什么地方呢?请看下面例子:

  1. @Test
  2. public void testString1() {
  3. String a = "123456";
  4. for (int i=0; i<10; i++) {
  5. a += "dfdsfdsfds";
  6. }
  7. System.out.println(a);
  8. }

  上面代码中,我们初始化了常量 a,并且在循环里面做了多次字符串的拼接,最终 a 的指针地址指向了字符串拼接后的结果。

  总结一下:

    1、字符拼接过程产生了一定的字符数组;且是不可修改的。

    2、每次改变字符串的值,就要重新生成一个String对象,然后将指针指向新的对象。

    3、多余的对象一定程度上增加了GC的工作量。

  综上,String 字符串拼接存在一定的性能消耗,但还不足以说性能低效;有比较才有优劣,再看看 StringBuilder 和 StringBuffer 内部又是做的呢?

  • StringBuilder

  StringBuilder 内部存储是字符数组,是可修改的;看一下父类:

  1. abstract class AbstractStringBuilder implements Appendable, CharSequence {
  2. /**
  3. * The value is used for character storage.
  4. */
  5. char[] value;
  6.  
  7. /**
  8. * The count is the number of characters used.
  9. */
  10. int count;

  添加字符串的方法是append,看看具体实现:

  1. public AbstractStringBuilder append(String str) {
  2. if (str == null)
  3. return appendNull();
  4. int len = str.length();
  5. ensureCapacityInternal(count + len);
  6. str.getChars(0, len, value, count);
  7. count += len;
  8. return this;
  9. }

 

  1. private void ensureCapacityInternal(int minimumCapacity) {
  2. // overflow-conscious code
  3. if (minimumCapacity - value.length > 0) {
  4. value = Arrays.copyOf(value,
  5. newCapacity(minimumCapacity));
  6. }
  7. }
  1. public static char[] copyOf(char[] original, int newLength) {
  2. char[] copy = new char[newLength];
  3. System.arraycopy(original, 0, copy, 0,
  4. Math.min(original.length, newLength));
  5. return copy;
  6. }

  这里对字符数组做了拷贝,底层的数组拷贝实现方法:

  1. public static native void arraycopy(Object src, int srcPos,
  2. Object dest, int destPos,
  3. int length);

  可以看到,底层调用 System.arraycopy 方法,而 arraycopy 方法是调用底层 C 语言实现的。

  通过上面的源码,得出一些结论:

    1、StringBuilder 在字符串拼接过程中,是对字符数组的修改;

    2、append 方法对数组做了动态扩容;

    3、最终实现是通过 System.arraycopy 调用 C 语言的方法;

  与 String 相比,由于 StringBuilder 是对数组的修改、动态扩容,减少了中间对象的生成,在一定程度上性能较优。

  • StringBuffer

  StringBuffer 与 StringBuilder 都继承了 AbstractStringBuilder;

  1. public final class StringBuffer
  2. extends AbstractStringBuilder
  3. implements java.io.Serializable, CharSequence
  4. {
  5.  
  6. /**
  7. * A cache of the last value returned by toString. Cleared
  8. * whenever the StringBuffer is modified.
  9. */
  10. private transient char[] toStringCache;
  1. @Override
  2. public synchronized StringBuffer append(String str) {
  3. toStringCache = null;
  4. super.append(str);
  5. return this;
  6. }

  不同的是 StringBuffer 添加了同步锁,是线程安全的;

小结:

  在字符串拼接上,不考虑线程安全的情况下 StringBuilder 优于 StringBuffer,StringBuffer 优于 String;StringBuffer 是线程安全的。

关于 String,StringBuilder,StringBuffer的更多相关文章

  1. 深入源码剖析String,StringBuilder,StringBuffer

    [String,StringBuffer,StringBulider] 深入源码剖析String,StringBuilder,StringBuffer [作者:高瑞林] [博客地址]http://ww ...

  2. String, StringBuilder, StringBuffer问题

    1. 区别 String为字符串常量,而StringBuilder和StringBuffer都是字符串变量,其中StringBuilder线程非安全,StringBuffer线程安全. 每次对 Str ...

  3. String StringBuilder StringBuffer区别

    String StringBuilder StringBuffer String类是final类,不可以被继承,且它的成员方法也是final方法,当一个字符串对象进行操作操作时,任何的改变不会影响到这 ...

  4. difference among String,StringBuilder,StringBuffer

    difference among String,StringBuilder,StringBuffer String常用构造函数 String(byte[] bytes) String(byte[] b ...

  5. JDK源码分析系列---String,StringBuilder,StringBuffer

    JDK源码分析系列---String,StringBuilder,StringBuffer 1.String public final class String implements java.io. ...

  6. java中String StringBuilder StringBuffer比较和效率(性能)测试

    string stringbuilder stringbuffer三者的区别 从JDK源码看,String.StringBuilder.StringBuffer都是存放在char[] 数组字符串. 简 ...

  7. string,stringbuilder,stringbuffer用法

    总结:1.如果要操作少量的数据用 = String   ==================================>字符串常量2.单线程操作字符串缓冲区 下操作大量数据 = Strin ...

  8. java中string stringbuilder stringbuffer 的区别

    1. String 类 String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间. String a = "a&qu ...

  9. String,StringBuilder,StringBuffer

    (转:http://blog.csdn.net/rmn190/article/details/1492013)   String 字符串常量StringBuffer 字符串变量(线程安全)String ...

  10. String Stringbuilder Stringbuffer的区别

    String 字符串常量StringBuffer 字符串变量(线程安全)StringBuilder 字符串变量(非线程安全) 简要的说, String 类型和 StringBuffer 类型的主要性能 ...

随机推荐

  1. hi-nginx-1.3.4编译安装

    hi-nginx既是 web 服务器,也是 application 服务器.它开源在https://github.com/webcpp/hi-nginx 它是NGINX的超集,因此与编译NGINX稍有 ...

  2. poj-1146 ID codes

    Description It is 2084 and the year of Big Brother has finally arrived, albeit a century late. In or ...

  3. 关于Mysql DATE_FORMAT() 日期格式

    定义和用法 DATE_FORMAT() 函数用于以不同的格式显示日期/时间数据. 语法 DATE_FORMAT(date,format) date 参数是合法的日期.format 规定日期/时间的输出 ...

  4. centos7 yum 安装mariadb

    #vim /etc/yum.repos.d/mariadb.repo [mariadb]name = MariaDBbaseurl = https://yum.mariadb.org/10.1.16/ ...

  5. /var/spool/clientmqueue目录下存在大量文件的原因及解决方法

    问题现象:linux操作系统中的/var/spool/clientmqueue/目录下存在大量文件.原因分析: 系统中有用户开启了cron,而cron中执行的程序有输出内容,输出内容会以邮件形式发给c ...

  6. Jquery判断单选框是否选中和获取选中的值

    第一种:利用选中值判断选中 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http ...

  7. 发布利用 Qt Assistant来做帮助系统的程序遇到的问题

    最近,一直在做反演初始模型可视化建模的软件 model Constraint,最后的步骤就是利用 Qt Assistant为自己的程序制作帮助系统. 1.<Qt Creator快速入门>和 ...

  8. beta冲刺6

    前言:此篇是补昨天凌晨的.后面有更新但是太晚了就没有即使更新.所以现在过来更新一下. 昨天的未完成: 用户测试+测试报告 目前剩下的功能点:输入内容检测 我的社团输出显示格式调整. 今天的完成: 我的 ...

  9. python 操作SQLAlchemy

    SQLAlchemy python链接 pymysql mysql+pymysql://<username>:<password>@<host>/<dbnam ...

  10. Web前端性能分析

    Web前端性能通常上代表着一个完全意义上的用户响应时间,包含从开始解析HTML文件到最后渲染完成开始的整个过程,但不包括在输入url之后与服务器的交互阶段.下面是整个过程的各个步骤: 开始解析html ...