Java:String、StringBuffer和StringBuilder区别

String:字符串常量
StringBuffer:字符串变量(线程安全)
StringBuilder:字符串变量(非线程安全)

String与StringBuffer区别:
主要区别在于StringBuffer内容可变。也就是说如果觉得该字符串内容是可变的,那么最好就使用StringBuffer。这样可以减少内存的消耗。

StringBuffer name = new StringBuffer("Name");
StringBuffer password = new StringBuffer("Password");
name.append(password);

代码很简单,就是新建了两个StringBuffer类。然后将password对象的内容加到name上。我们跟进append()函数。

public synchronized StringBuffer append(StringBuffer sb) {
    toStringCache = null;
    super.append(sb);
    return this;
}

首先线程安全就是通过synchronized关键字实现的。这样可以保证只有一个线程调用name中的append()。
看看toStringCache这个变量,是用于存储toString()方法的缓存。如果StringBuffer被修改了就变成了null。我们看看toString()方法:

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

如果toStringCache 为null,则先构建。然后返回字符串。

我们跟进一下super.append(sb);这个方法

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

可以看出,如果sb为空,则返回null。
如果sb不为空,则得到sb的长度,然后调用了ensureCapacityInternal(int)函数。
我们跟进一下

private void ensureCapacityInternal(int minimumCapacity) {
    if (minimumCapacity - value.length > 0)
       expandCapacity(minimumCapacity);
}

可以看出,这个函数首先判断value【char数组】的长度是否能满足增加后的长度。如果不满足,就调用了expandCapacity(int)方法,我们跟进一下。

 void expandCapacity(int minimumCapacity) {
    int newCapacity = value.length * 2 + 2;
    if (newCapacity - minimumCapacity < 0)
        newCapacity = minimumCapacity;
    if (newCapacity < 0) {
        if (minimumCapacity < 0) // overflow
            hrow new OutOfMemoryError();
        newCapacity = Integer.MAX_VALUE;
    }
    value = Arrays.copyOf(value, newCapacity);
}

首先,StringBuffer类相当于是有个Capacity,默认大小为16。当然在创建的时候也可以自定义Capacity的大小。然后如果不满足要求,我们就进行扩充。一般来说扩充后的长度为当前长度*2+2,也就是说不出意外,当长度为17时,StringBuffer类的Capacity大小为34。以此类推。但是,如果扩充后的长度为40,则代表着34不能满足要求。所以就扩充40长度,然后调用Arrays.copyOf()方法,将append后的值赋给value。

这里只说了append()函数的方法,而其他的函数实现过程类似。

而StringBuffer由于使用了线程安全技术,所以在运行上会稍慢些。而String是字符常量。在引用时会更快。但是,如果已知字符串内容会改变,就不考虑用String了,因为String常量会更消耗内存。

而StringBuilder与StringBuffer类似。内容可变,实现的方法基本类似。只是不同的是,StringBuilder并未实现线程安全技术。但是也就意味着它会比StringBuffer处理起来更快。

猜你喜欢

转载自blog.csdn.net/new_Aiden/article/details/50976478