StringBuffer 与StringBuilder 源码解析(以及String)

参考:

 https://blog.csdn.net/rusbme/article/details/51389623

https://blog.csdn.net/matrix5267/article/details/62423340

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

StringBuilder 字符串变量(非线程安全)


 String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。

String a= new String("hello");

1:在栈内存中定义了一个a对象引用,指向堆内存的值“hello”内存地址。最终开辟了一个内存空间

2:在栈内存重定义了一个a对象引用,先指向堆内存值为“hello”内存地址,然后又指向new之后堆内存为“hello”的地址。最终开辟了两个空间,第一个空间没有对象引用,会被JVM垃圾回收。

str += "andy";

str的值不是也改变了吗?

其实上述代码在内存中已经开辟了3个空间,分别是:”hello“, ”andy“, ”helloandy“,他们的堆内存大小是固定的,最终str指向了”helloandy“的堆地址。 而StringBuffer使用时,只会开辟一块内存空间,可以使用append添加delete等操作内容。


首先我们来看两个类的继承体系

public final class StringBuilder extends AbstractStringBuilder implements
        Appendable, CharSequence, Serializable;

public final class StringBuffer extends AbstractStringBuilder implements
        Appendable, Serializable, CharSequence

AbstravtStringBuilder类

 private char[] value;
    static final int INITIAL_CAPACITY = 16;
    AbstractStringBuilder() {
        value = new char[INITIAL_CAPACITY];
    }

    AbstractStringBuilder(int capacity) {
        if (capacity < 0) {
            throw new NegativeArraySizeException(Integer.toString(capacity));
        }
        value = new char[capacity];
    }
      AbstractStringBuilder(String string) {
        count = string.length();
        shared = false;
        value = new char[count + INITIAL_CAPACITY];
        string.getCharsNoCheck(0, count, value, 0);
    }

构造函数:

//两个类的构造方法完全相同,都是调用父类的构造函数,并且留有16的空间
publicStringBuilder() {
    super(16);
}
public StringBuilder(int capacity) {
    super(capacity);
}
public StringBuilder(String str) {
    super(str.length() + 16);
    append(str);
}
public StringBuilder(CharSequence seq) {
    this(seq.length() + 16);
    append(seq);
}

默认初始容量为16,当然我们也可以自己设置容量大小;接着我们看看拼接过程

final void append0(char[] chars) {
        int newCount = count + chars.length;
        if (newCount > value.length) {
            enlargeBuffer(newCount);
        }
        System.arraycopy(chars, 0, value, count, chars.length);
        count = newCount;
    }

接下来我们看看SB 扩容过程

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

尝试将新容量扩为大小变成2倍+2 ,容量如果不够,直接扩充到需要的容量大小。所以我们在创建SB的时候,可以估算新字符串的长度来适当避免多次扩容,影响效率。


基本方法:
append

//先看StringBuilder
public StringBuilder append(Object obj) {
    return append(String.valueOf(obj));
}

//StringBuffer,CharSequence,char[]与之类似
public StringBuilder append(String str) {
    super.append(str);
    return this;
}

//boolean,char,long,float,double与之类似
public StringBuilder append(int i) {
    super.append(i);
    return this;
}

//StringBuffer
public synchronized StringBuffer append(Object obj) {
    toStringCache = null;
    super.append(String.valueOf(obj));
    return this;
}

//StringBuffer,CharSequence,char[]与之类似
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

//boolean,char,long,float,double与之类似
public synchronized StringBuffer append(int i) {
    toStringCache = null;
    super.append(i);
    return this;
}

insert

//StringBuilder
public StringBuilder insert(int index, char[] str, int offset,
                            int len)
{
    super.insert(index, str, offset, len);
    return this;
}

public StringBuilder insert(int offset, Object obj) {
        super.insert(offset, obj);
        return this;
}

public StringBuilder insert(int offset, int i) {
    super.insert(offset, i);
    return this;
}

//StringBuffer
publicsynchronized StringBuffer insert(int index, char[] str, int offset,
                                        int len)
{
    toStringCache = null;
    super.insert(index, str, offset, len);
    return this;
}

public synchronized StringBuffer insert(int offset, Object obj) {
    toStringCache = null;
    super.insert(offset, String.valueOf(obj));
    return this;
}

public StringBuffer insert(int offset, int i) {
    // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
    // after conversion of i to String by super class method
    // Ditto for toStringCache clearing
    super.insert(offset, i);
    return this;
}
 
 
  • 3
  • 4
  • 5

delete

//StringBuilder
publicStringBuilder delete(int start, int end) {
    super.delete(start, end);
    return this;
}

public StringBuilder deleteCharAt(int index) {
    super.deleteCharAt(index);
    return this;
}

public StringBuilder replace(int start, int end, String str) {
    super.replace(start, end, str);
    return this;
}
//StringBuffer
public synchronized StringBuffer delete(int start, int end) {
    toStringCache = null;
    super.delete(start, end);
    return this;
}

public synchronized StringBuffer deleteCharAt(int index) {
    toStringCache = null;
    super.deleteCharAt(index);
    return this;
}

public synchronized StringBuffer replace(int start, int end, String str) {
    toStringCache = null;
    super.replace(start, end, str);
    return this;
}

reverser


public StringBuilder reverse() {
    super.reverse();
    return this;
}

publicsynchronized StringBuffer reverse() {
    toStringCache = null;
    super.reverse();
    return this;
}

toString

//StringBuilder
public String toString() {
    // Create a copy, don't share the array
    return new String(value, 0, count);
}

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

StringBuffer独有:


//如果一个方法修改了value,那么同步使用length()方法就会出问题
public synchronized int length() {
    return count;
}

public synchronized int capacity() {
    return value.length;
}

public synchronized void ensureCapacity(int minimumCapacity) {
    if (minimumCapacity > value.length) {
        expandCapacity(minimumCapacity);
    }
}

//同样的道理,这个也加了synchronized
public synchronized char charAt(int index) {
    if ((index < 0) || (index >= count))
        throw new StringIndexOutOfBoundsException(index);
    return value[index];
}

public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,
                                  int dstBegin)
{
    super.getChars(srcBegin, srcEnd, dst, dstBegin);
}
public synchronized void setLength(int newLength) {
    toStringCache = null;
    super.setLength(newLength);
}

public synchronized void setCharAt(int index, char ch) {
    if ((index < 0) || (index >= count))
        throw new StringIndexOutOfBoundsException(index);
    toStringCache = null;
    value[index] = ch;
}
public synchronized String substring(int start) {
    return substring(start, count);
}

public synchronized String substring(int start, int end) {
    return super.substring(start, end);
}

publicsynchronized CharSequence subSequence(int start, int end) {
    return super.substring(start, end);
}




猜你喜欢

转载自blog.csdn.net/duoduo18up/article/details/80010789