StringBuilder:java
1、構造方法:數組
/** * Constructs a string builder with no characters in it and an * initial capacity of 16 characters. */ public StringBuilder() { super(16); } /** * Constructs a string builder with no characters in it and an * initial capacity specified by the <code>capacity</code> argument. * * @param capacity the initial capacity. * @throws NegativeArraySizeException if the <code>capacity</code> * argument is less than <code>0</code>. */ public StringBuilder(int capacity) { super(capacity); } /** * Constructs a string builder initialized to the contents of the * specified string. The initial capacity of the string builder is * <code>16</code> plus the length of the string argument. * * @param str the initial contents of the buffer. * @throws NullPointerException if <code>str</code> is <code>null</code> */ public StringBuilder(String str) { super(str.length() + 16); append(str); } /** * Constructs a string builder that contains the same characters * as the specified <code>CharSequence</code>. The initial capacity of * the string builder is <code>16</code> plus the length of the * <code>CharSequence</code> argument. * * @param seq the sequence to copy. * @throws NullPointerException if <code>seq</code> is <code>null</code> */ public StringBuilder(CharSequence seq) { this(seq.length() + 16); append(seq); }
從代碼可知,StringBuilder的無論哪一個構造方法,都用到了父類AbstractStringBuilder的構造方法,那麼來看一下它的父類AbstractStringBuilder。安全
成員變量+構造方法:多線程
/** * The value is used for character storage. */ char[] value; /** * The count is the number of characters used. */ int count; /** * This no-arg constructor is necessary for serialization of subclasses. */ AbstractStringBuilder() { } /** * Creates an AbstractStringBuilder of the specified capacity. */ AbstractStringBuilder(int capacity) { value = new char[capacity]; }
從該父類就能夠看出,StringBuilder與String同樣是經過char數組value來存字符串,但不同的是這個value數組沒有用final修飾,這也是StringBuilder能夠直接經過改變value作字符串拼接的緣由。StringBuilder能夠直接經過構造方法直接初始化value容量大小,值得注意的是,AbstractStringBuilder類擁有一個變量count,用來表示char數組中字符串真實長度,故如下兩個方法,length方法返回的是該StringBuilder中字符串的真實長度,capacity方法返回的是value數組的容量。app
/** * Returns the length (character count). * * @return the length of the sequence of characters currently * represented by this object */ public int length() { return count; } /** * Returns the current capacity. The capacity is the amount of storage * available for newly inserted characters, beyond which an allocation * will occur. * * @return the current capacity */ public int capacity() { return value.length; }
成員方法:less
append方法:ui
public StringBuilder append(Object obj) { return append(String.valueOf(obj)); } public StringBuilder append(String str) { super.append(str); return this; } // Appends the specified string builder to this sequence. private StringBuilder append(StringBuilder sb) { if (sb == null) return append("null"); int len = sb.length(); int newcount = count + len; if (newcount > value.length) expandCapacity(newcount); sb.getChars(0, len, value, count); count = newcount; return this; } /** * Appends the specified <tt>StringBuffer</tt> to this sequence. * <p> * The characters of the <tt>StringBuffer</tt> argument are appended, * in order, to this sequence, increasing the * length of this sequence by the length of the argument. * If <tt>sb</tt> is <tt>null</tt>, then the four characters * <tt>"null"</tt> are appended to this sequence. * <p> * Let <i>n</i> be the length of this character sequence just prior to * execution of the <tt>append</tt> method. Then the character at index * <i>k</i> in the new character sequence is equal to the character at * index <i>k</i> in the old character sequence, if <i>k</i> is less than * <i>n</i>; otherwise, it is equal to the character at index <i>k-n</i> * in the argument <code>sb</code>. * * @param sb the <tt>StringBuffer</tt> to append. * @return a reference to this object. */ public StringBuilder append(StringBuffer sb) { super.append(sb); return this; } /** */ public StringBuilder append(CharSequence s) { if (s == null) s = "null"; if (s instanceof String) return this.append((String)s); if (s instanceof StringBuffer) return this.append((StringBuffer)s); if (s instanceof StringBuilder) return this.append((StringBuilder)s); return this.append(s, 0, s.length()); } /** * @throws IndexOutOfBoundsException {@inheritDoc} */ public StringBuilder append(CharSequence s, int start, int end) { super.append(s, start, end); return this; } public StringBuilder append(char[] str) { super.append(str); return this; } /** * @throws IndexOutOfBoundsException {@inheritDoc} */ public StringBuilder append(char[] str, int offset, int len) { super.append(str, offset, len); return this; } public StringBuilder append(boolean b) { super.append(b); return this; } public StringBuilder append(char c) { super.append(c); return this; } public StringBuilder append(int i) { super.append(i); return this; } public StringBuilder append(long lng) { super.append(lng); return this; } public StringBuilder append(float f) { super.append(f); return this; } public StringBuilder append(double d) { super.append(d); return this; }
能夠看出StringBuilder的append方法仍是來自它的父類AbstractStringBuilder,直接貼上父類append,只列出幾個經常使用的this
/** * Appends the string representation of the {@code Object} argument. * <p> * The overall effect is exactly as if the argument were converted * to a string by the method {@link String#valueOf(Object)}, * and the characters of that string were then * {@link #append(String) appended} to this character sequence. * * @param obj an {@code Object}. * @return a reference to this object. */ public AbstractStringBuilder append(Object obj) { return append(String.valueOf(obj)); } /** * Appends the specified string to this character sequence. * <p> * The characters of the {@code String} argument are appended, in * order, increasing the length of this sequence by the length of the * argument. If {@code str} is {@code null}, then the four * characters {@code "null"} are appended. * <p> * Let <i>n</i> be the length of this character sequence just prior to * execution of the {@code append} method. Then the character at * index <i>k</i> in the new character sequence is equal to the character * at index <i>k</i> in the old character sequence, if <i>k</i> is less * than <i>n</i>; otherwise, it is equal to the character at index * <i>k-n</i> in the argument {@code str}. * * @param str a string. * @return a reference to this object. */ public AbstractStringBuilder append(String str) { if (str == null) str = "null"; int len = str.length(); ensureCapacityInternal(count + len); str.getChars(0, len, value, count); count += len; return this; } // Documentation in subclasses because of synchro difference public AbstractStringBuilder append(StringBuffer sb) { if (sb == null) return append("null"); int len = sb.length(); ensureCapacityInternal(count + len); sb.getChars(0, len, value, count); count += len; return this; }
經過能夠看出以上代碼看出兩點:1.append對傳入的參數進行了判空,且爲空是將字符串「null」拼接了進去,與String類型的‘+’拼接null字符串同樣spa
2.若是values的容量大小不足以裝下拼接後的字符串,會重建一個value,並將以前的value複製進去,具體反映在:線程
/** * This method has the same contract as ensureCapacity, but is * never synchronized. */ private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code if (minimumCapacity - value.length > 0) expandCapacity(minimumCapacity); } /** * This implements the expansion semantics of ensureCapacity with no * size check or synchronization. */ 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); } public static char[] copyOf(char[] original, int newLength) { char[] copy = new char[newLength]; System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; }
StringBuffer:
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence
經過StringBuffer類的定義及構造方法,咱們能夠看到其實和StringBuilder很是相似甚至徹底同樣,沒必要多說,StringBuffer也是經過char數組value
來存字符串,且同樣是沒有final修飾。
append方法:
public synchronized StringBuffer append(Object obj) { super.append(String.valueOf(obj)); return this; } public synchronized StringBuffer append(String str) { super.append(str); return this; } /** * Appends the specified <tt>StringBuffer</tt> to this sequence. * <p> * The characters of the <tt>StringBuffer</tt> argument are appended, * in order, to the contents of this <tt>StringBuffer</tt>, increasing the * length of this <tt>StringBuffer</tt> by the length of the argument. * If <tt>sb</tt> is <tt>null</tt>, then the four characters * <tt>"null"</tt> are appended to this <tt>StringBuffer</tt>. * <p> * Let <i>n</i> be the length of the old character sequence, the one * contained in the <tt>StringBuffer</tt> just prior to execution of the * <tt>append</tt> method. Then the character at index <i>k</i> in * the new character sequence is equal to the character at index <i>k</i> * in the old character sequence, if <i>k</i> is less than <i>n</i>; * otherwise, it is equal to the character at index <i>k-n</i> in the * argument <code>sb</code>. * <p> * This method synchronizes on <code>this</code> (the destination) * object but does not synchronize on the source (<code>sb</code>). * * @param sb the <tt>StringBuffer</tt> to append. * @return a reference to this object. * @since 1.4 */ public synchronized StringBuffer append(StringBuffer sb) { super.append(sb); return this; }
能夠看到與StringBuilder惟一不一樣的是每一個append方法都加了synchronized修飾,即鎖(不容許多線程同時訪問),這也是StringBuffer是線程安全的,StringBuilder是線程不安全的緣由