一直以来,都是看到网上说“ StringBuilder是线程不安全的,但运行效率高;StringBuffer 是线程安全的,但运行效率低”,然后默默记住:一个是线程安全、一个线程不安全,但对内在原因并不了解。这两天终于下定决心看了下源代码,才深刻理解为啥一个线程安全、一个非线程安全。
一名话总结:java.lang.StringBuilder 与 java.lang.StringBuffer 同是继承于 java.lang.AbstractStringBuilder,具体在功能实现大多在 AbstractStringBuilder 中,StringBuilder 和 StringBuffer 相当于对其进行的一个接口封装,区别只是一个作了同步封装、一个作非同步封装。
由表及里,首先从 StringBuilder 和 StringBuffer 源代码中的构造方法和 append,delete,replace,insert,toString 等方法研究起。
StringBuilder 是一个 final 类,不能被继承。其类继承父类和实现的接口关系如下所示:
1 public final class StringBuilder 2 extends AbstractStringBuilder 3 implements java.io.Serializable, CharSequence 4 {}
其内部代码中显式声明(不包括继承等隐式属性)的只有一个属性:serialVersionUID(序列化ID)。其构造方法的内部实现也是通过 super 方法调用父类构造方法实现,具体如下所示:
1 /** 2 * Constructs a string builder with no characters in it and an 3 * initial capacity of 16 characters. 4 */ 5 public StringBuilder() { 6 super(16); 7 } 8 9 /** 10 * Constructs a string builder with no characters in it and an 11 * initial capacity specified by the <code>capacity</code> argument. 12 * 13 * @param capacity the initial capacity. 14 * @throws NegativeArraySizeException if the <code>capacity</code> 15 * argument is less than <code>0</code>. 16 */ 17 public StringBuilder(int capacity) { 18 super(capacity); 19 } 20 21 /** 22 * Constructs a string builder initialized to the contents of the 23 * specified string. The initial capacity of the string builder is 24 * <code>16</code> plus the length of the string argument. 25 * 26 * @param str the initial contents of the buffer. 27 * @throws NullPointerException if <code>str</code> is <code>null</code> 28 */ 29 public StringBuilder(String str) { 30 super(str.length() + 16); 31 append(str); 32 } 33 34 /** 35 * Constructs a string builder that contains the same characters 36 * as the specified <code>CharSequence</code>. The initial capacity of 37 * the string builder is <code>16</code> plus the length of the 38 * <code>CharSequence</code> argument. 39 * 40 * @param seq the sequence to copy. 41 * @throws NullPointerException if <code>seq</code> is <code>null</code> 42 */ 43 public StringBuilder(CharSequence seq) { 44 this(seq.length() + 16); 45 append(seq); 46 }