StringBuilder和StringBuffer

  前面讲到String是不可变的,如果需要可变的字符串将如何使用和操作呢?JAVA提供了连个操作可变字符串的类,StringBuilder和StringBuffer,从源码中可以看到这两个类都是采用final修饰,并且继承抽象类AbstractStringBuilder的。

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    /**
     * The value is used for character storage.
     */
    char[] value;

    /**
     * The count is the number of characters used.
     */
    int count;
}

  同String相同,都是采用字符数组来存储的,但是String中使用final修饰,是不可变的。

  StringBuffer和StringBuilder都提供了一些常用的操作字符串的方法,有什么不同之处呢?还是从源码着手分析:

StringBuffer源码解析

  /**
     * Constructs a string buffer with no characters in it and an
     * initial capacity of 16 characters.
     */
    public StringBuffer() {
        super(16);
    }

  看AbstractStringBuilder可知:

AbstractStringBuilder(int capacity) {
  value = new char[capacity];
}

  无参构造函数,构造一个初始容量为16的字符串缓冲区。同时提供多个有参的构造函数,其中:

  /**
     * Constructs a string buffer initialized to the contents of the
     * specified string. The initial capacity of the string buffer is
     * {@code 16} plus the length of the string argument.
     *
     * @param   str   the initial contents of the buffer.
     */
    public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
    }

  这个构造函数需提供一个字符串参数,构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容,该字符串的初始容量为 16 加上字符串参数的长度。其中的append方法是重要部分。

    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

    // AbstractStringBuilder
    public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

  append方法前加了同步锁,保证了线程安全,StringBuffer中很多方法都采用同步锁,保证了多线程操作时的同步安全。

  其中的ensureCapacityInternal方法中对存储空间的分配:当存储空间不够用的时候,重新new char[],存储空间为:(原始大小+1)*2,最大为:Integer.MAX_VALUE ,

StringBuilder

  StringBuilder通StringBuffer操作逻辑基本一致,只是没有做同步处理。

总结

  String:字符常量

  StringBuffer:字符变量【线程安全】

  StringBuilder:字符变量【非线程安全】

  由此也可知,在大部分情况下,三者在执行速度方面的比较:StringBuilder >  StringBuffer  >  String

  用法总结:

  String:用于少量需要对字符串进行操作【因为String 每次生成对象都会对系统性能产生影响,当内存中无引用对象产生过多时,GC就会开始工作】

  StringBuilder:单线程下,多次大量操作字符串【字符串处理时不会产生新的对象,而是对象自身做改变】

  StringBuffer:多线程下,多次大量操作字符串【字符串处理时不会产生新的对象,而是对象自身做改变】

源码记:苦人所不苦,能人所不能,所谓成也
声明:原创博客请在转载时保留原文链接或者在文章开头加上本人博客地址,如发现错误,欢迎批评指正。  

JDK源码学习--String篇(四) 终结篇的更多相关文章

  1. JDK源码学习--String篇(二) 关于String采用final修饰的思考

    JDK源码学习String篇中,有一处错误,String类用final[不能被改变的]修饰,而我却写成静态的,感谢CTO-淼淼的指正. 风一样的码农提出的String为何采用final的设计,阅读JD ...

  2. JDK源码学习--String篇(三) 存储篇

    在进一步解读String类时,先了解下内存分配和数据存储的. 数据存储 1.寄存器:最快的存储区,位于处理器的内部.由于寄存器的数量有限,所以寄存器是按需分配. 2.堆栈:位于RAM中,但是通过堆栈指 ...

  3. JDK源码学习--String篇(-)

    工作三年了,用了三年的JAVA,突然发现竟然没有好好的看下JDK的源码,整天用着的String,只是大概知道怎么回事,其中的实现逻辑却是一头雾水. 知耻而后勇,加油!!! java.lang.Stri ...

  4. JDK源码学习系列03----StringBuffer+StringBuilder

                         JDK源码学习系列03----StringBuffer+StringBuilder 由于前面学习了StringBuffer和StringBuilder的父类A ...

  5. JDK源码学习系列01----String

                                                     JDK源码学习系列01----String 写在最前面: 这是我JDK源码学习系列的第一篇博文,我知道 ...

  6. JDK源码学习系列02----AbstractStringBuilder

     JDK源码学习系列02----AbstractStringBuilder 因为看StringBuffer 和 StringBuilder 的源码时发现两者都继承了AbstractStringBuil ...

  7. JDK源码学习笔记——LinkedHashMap

    HashMap有一个问题,就是迭代HashMap的顺序并不是HashMap放置的顺序,也就是无序. LinkedHashMap保证了元素迭代的顺序.该迭代顺序可以是插入顺序或者是访问顺序.通过维护一个 ...

  8. JDK1.8源码学习-String

    JDK1.8源码学习-String 目录 一.String简介 String类是Java中最常用的类之一,所有字符串的字面量都是String类的实例,字符串是常量,在定义之后不能被改变. 二.定义 p ...

  9. JDK源码学习系列05----LinkedList

                                             JDK源码学习系列05----LinkedList 1.LinkedList简介 LinkedList是基于双向链表实 ...

随机推荐

  1. JS 匿名函数 自执行

    其实就是将函数直接做为表达调用,使用括号包裹定义函数体,解析器将会以函数表达式的方式去调用定义函数. 常见格式:(function() { /* code */ })(); 解释:包围函数(funct ...

  2. div内嵌p,div等块元素出现的问题

    div内嵌p,div等块元素出现的问题 http://caiceclb.iteye.com/blog/428085 div内部块级元素,比如p,div,设置外间距(margin)的话会怎样.本来还纳闷 ...

  3. SQLSERVER分布式事务使用实例

    实例一 尊重原著作:本文参考自http://www.jb51.net/article/43540.htm --BEGIN DISTRIBUTED TRANSACTION [transactionnam ...

  4. C# List<T>中Select List Distinct()去重复

    List<ModelJD> data = myDalJD.GetAllDataList(); List<string> list= new List<string> ...

  5. ORA-600[kcratr_scan_lastbwr]逻辑坏块解决

    数据库版本: 11.2.0.3 问题现象: 今天在启动一台测试数据库的时候,发现db不能open,报错如下: ERROR at line 1: ORA-00600: internal error co ...

  6. leetcode Binary Tree Paths python

    # Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x): # self.val = ...

  7. 生成php所需要的APNS Service pem证书的步骤

    1.登录到 iPhone Developer Connection Portal 并点击 App IDs 2.创建一个不使用通配符的 App ID .通配符 ID 不能用于推送通知服务.例如,我们的i ...

  8. windbg命令学习4

    4.查看调用栈 k命令:显示的是一定数量的栈帧, 其中帧的数量是由.kframes命令来控制的, 默认值是256. 我们如何来判断函数的栈指针,参数地址和局部变量地址呢? 举一个简单的windbg的k ...

  9. SQL Server 固定角色

    1. 查看固定服务器角色 execute sp_helpsrvrole; 管理: execute master..sp_addsrvrolemember @logingName='neeky' @ro ...

  10. 6. java.lang.IllegalArgumentException

    方法的参数错误 比如g.setColor(int red,int green,int blue)这个方法中的三个值,如果有超过255的也会出现这个异常,因此一旦发现这个异常,我们要做的,就是赶紧去检查 ...