String、StringBuffer、StringBuilder区别

一、String、StringBuffer、StringBuilder区别

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

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"这个字符串对象是线程安全的。

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

    @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);
    }

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

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

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

参考:
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会每次循环就创建一个新对象
参考:https://www.cnblogs.com/aipan/p/7443832.html

posted @ 2018-11-29 15:02  zeroingToOne  阅读(406)  评论(0编辑  收藏  举报