二十四桥仍在,波心荡、冷月无声。
——姜夔《扬州慢》
## Java基础之StringBuffer和StringBuilder
1. 前言-浅谈String:
- String 类中使用 final 关键字修饰字符数组来保存字符串, private final char value[] ,所以String 对象是不可变的。
 
- String 中的对象是不可变的,也就可以理解为常量,线程安全。
 
- 每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。
 
- String类传送门…
 
2. 可变的StringBuffer和StringBuilder
- StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在AbstractStringBuilder 中也是使用字符数组保存字符串 char[] value 但是没有用 final 关键字修饰,所以这两种对象都是可变的。
 
- StringBuilder 与 StringBuffer 的构造方法都是调用父类构造方法也就是 AbstractStringBuilder 实现的,大家可以看下面的源码分析。
 
3. 线程安全性
AbstractStringBuilder 是 StringBuilder 与StringBuffer 的公共父类,定义了一些字符串的基本操作,如 append、insert、indexOf 等公共方法。
- StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
 
- StringBuilder 并没有对方法进行加同步锁,所以是线程不安全的。
 
4. 性能
StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。
相同情况下使用StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
5. AbstractStringBuilder部分源码
可变的字符序列–基于JDK1.8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | 
 
  abstract class AbstractStringBuilder implements Appendable, CharSequence {        char[] value;   int count;           AbstractStringBuilder() {  }      AbstractStringBuilder(int capacity) {     value = new char[capacity];  }   }
 
  | 
 
5.1   StringBuffer部分源码
注意StringBuffer中方法中的synchronized锁。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
   | public final class StringBuffer extends AbstractStringBuilder     implements java.io.Serializable, CharSequence{
     
 
 
     private transient char[] toStringCache;         static final long serialVersionUID = 3388685877147921107L;
     
 
 
     public StringBuffer() {        super(16);    }
     public StringBuffer(int capacity) {        super(capacity);    }
     public StringBuffer(String str) {        super(str.length() + 16);        append(str);    }
     public StringBuffer(CharSequence seq) {        this(seq.length() + 16);        append(seq);    }
     @Override    public synchronized int length() {        return count;    }
     @Override    public synchronized int capacity() {        return value.length;    }        
 
     @Override    public synchronized StringBuffer append(String str) {        toStringCache = null;        super.append(str);        return this;    }    
 
     @Override    public synchronized StringBuffer insert(        int index, char[] str, int offset,int len    ){        toStringCache = null;        super.insert(index, str, offset, len);        return this;    } }
   | 
 
对length()和capacity()两个方法以及默认构造器的测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   |   public static void main(String[] args) {       StringBuffer stringBuffer = new StringBuffer();       stringBuffer.append("dd");       stringBuffer.append("ai");       stringBuffer.append("mm");       
 
 
        System.out.println("stringBuffer.length() = " + stringBuffer.length());       System.out.println("stringBuffer.capacity() = " + stringBuffer.capacity());          }
 
 
 
 
 
  | 
 
一系列的重载方法:

5.2 StringBuilder部分源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
   | public final class StringBuilder extends AbstractStringBuilder     implements java.io.Serializable, CharSequence {
           static final long serialVersionUID = 4383685877147921099L;               public StringBuilder() {         super(16);     }          public StringBuilder(int capacity) {         super(capacity);     }
      public StringBuilder(String str) {         super(str.length() + 16);         append(str);     }
           @Override     public StringBuilder append(String str) {         super.append(str);         return this;     }          public StringBuilder append(StringBuffer sb) {         super.append(sb);         return this;     }               @Override     public StringBuilder insert(         int index, char[] str, int offset,int len     ){         super.insert(index, str, offset, len);         return this;     }           }
   | 
 
6. 小结:
- 操作少量的数据: 适用String
 
- 单线程操作字符串缓冲区下操作大量数据: 适用StringBuilder
 
- 多线程操作字符串缓冲区下操作大量数据: 适用StringBuffer