String、StringBuffer、StringBuilder区别

1、String、StringBuffer、StringBuilder区别html

1.可变与不可变
(1). String类中使用字符数组保存字符串,由于有“final”修饰符,因此string对象是不可变的。segmentfault

private final char value[];

(2). StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,这两种对象都是可变的。数组

char[] value; //char数组的初始长度为16

2.是否多线程安全
(1). String中的对象是不可变的,也就能够理解为常量,显然线程安全。(这里的不可变能够理解成:String类型对象自己是不可变的)
线程安全能够理解为共享变量值是安全的,而String用final修饰,会被存储到一个叫作常量池的内存区域。安全

但什么又会以为String是能够被修改的,那么String的线程安全是怎么来的呢多线程

String a="test";
a="test1"

这里a就变成了test1,其实在这里是新建了一个"test1"字符串对象(若是常量池没有这个值的话就是新建)。而后将变量引用指向它。注意:这里并无修改"test"这个变量的内部状态,"test"这个字符串对象是线程安全的。app

(2). StringBuilder是非线程安全的
StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,因此是线程安全的。ide

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

    @Override
    public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }

2、StringBuffer、StringBuilder的相同点:
StringBuilder与StringBuffer有公共父类AbstractStringBuilder(抽象类)。优化

抽象类与接口的其中一个区别是:抽象类中能够定义一些子类的公共方法,子类只须要增长新的功能,不须要重复写已经存在的方法;而接口中只是对方法的申明和常量的定义。
StringBuilder、StringBuffer的方法都会调用AbstractStringBuilder中的公共方法,如super.append(...)、super.delete(...)、super.reverse()等。只是StringBuffer会在方法上加synchronized关键字,进行同步。ui

关于append方法:
使用append方法添加字符串的过程
(1). 先检查内部char[]数组是否须要扩容
(2). 如须要扩容则进行扩容,而后将原来元数据copy到新数组中。 (由于从新分配内存并拷贝的开销比较大,因此每次从新申请内存空间都是采用申请大于当前须要的内存空间的方式,这里是2倍。)
(3). 再将新添加的元数据加入到新char[]数组中this

参考:
https://blog.csdn.net/sinat_36705710/article/details/64440820
https://segmentfault.com/q/1010000007763710

速度
StringBuilder > StringBuffer > String (string要每次建立一个新对象)
可是在链接字符串的时候,String+的速度大于StringBuilder、StringBuffer,由于String+在编译期间作了优化
例:

String str = "a" + "bc"; //对于String+的赋值语句,在编译期间,直接将String赋值为abc

但如有成百上千个的链接字符串,把String+语句拆分红for循环语句时,String+的速度小于StringBuilder、StringBuffer,由于String会每次循环就建立一个新对象
参考:http://www.javashuo.com/article/p-pggmqgsd-gz.html

相关文章
相关标签/搜索