1. 程式人生 > >Java中String、StringBuilder、StringBuffer常用源碼分析及比較(三):String、StringBuilder、StringBuffer比較

Java中String、StringBuilder、StringBuffer常用源碼分析及比較(三):String、StringBuilder、StringBuffer比較

val str 成員變量 相同 += let .get end art

看這篇隨筆之前請務必先看前面兩章:

Java中String、StringBuilder、StringBuffer常用源碼分析及比較(一):String源碼分析

Java中String、StringBuilder、StringBuffer常用源碼分析及比較(二):StringBuilder、StringBuffer源碼分析

這裏講解了這三個類型的源碼,也或多或少的講解了他們的不同。

下面進入正題:

相同點:

一、成員變量:

  1.通過之前對源碼的分析,可以知道他們都是通過char數組value來存字符串的

  2.StringBuilder與StringBuffer都繼承自AbstractStringBuilder,且他們的構造方法基本都來自AbstractStringBuilder

  3.String、StringBuilder、StringBuffer都實現了CharSequence接口,,這個接口定義如下方法

/**
     * Returns the length of this character sequence.  The length is the number
     * of 16-bit <code>char</code>s in the sequence.</p>
     *
     * @return  the number of <code>char</code>s in this sequence
     
*/ int length(); /** * Returns the <code>char</code> value at the specified index. An index ranges from zero * to <tt>length() - 1</tt>. The first <code>char</code> value of the sequence is at * index zero, the next at index one, and so on, as for array * indexing. </p> * * <p>If the <code>char</code> value specified by the index is a * <a href="{@
docRoot}/java/lang/Character.html#unicode">surrogate</a>, the surrogate * value is returned. * * @param index the index of the <code>char</code> value to be returned * * @return the specified <code>char</code> value * * @throws IndexOutOfBoundsException * if the <tt>index</tt> argument is negative or not less than * <tt>length()</tt> */ char charAt(int index); /** * Returns a new <code>CharSequence</code> that is a subsequence of this sequence. * The subsequence starts with the <code>char</code> value at the specified index and * ends with the <code>char</code> value at index <tt>end - 1</tt>. The length * (in <code>char</code>s) of the * returned sequence is <tt>end - start</tt>, so if <tt>start == end</tt> * then an empty sequence is returned. </p> * * @param start the start index, inclusive * @param end the end index, exclusive * * @return the specified subsequence * * @throws IndexOutOfBoundsException * if <tt>start</tt> or <tt>end</tt> are negative, * if <tt>end</tt> is greater than <tt>length()</tt>, * or if <tt>start</tt> is greater than <tt>end</tt> */ CharSequence subSequence(int start, int end); /** * Returns a string containing the characters in this sequence in the same * order as this sequence. The length of the string will be the length of * this sequence. </p> * * @return a string consisting of exactly this sequence of characters */ public String toString();

二、成員方法:

  1.StringBuilder與StringBuffer中大多方法都來自於他們共同的父類AbstractStringBuilder,所實現的功能基本一模一樣。

不同點:

一、成員變量

  1.雖然String、StringBuilder、StringBuffer都是以char數組value來存字符串,但是String中value是final的(即構造方法初始化後無法被修改),而其余兩個卻沒有,所以再做拼接時,String需要不停的新建String對象,並用copy方法來實現拼接,而StringBuilder、StringBuffer則可在value容量足夠情況下在value後拼接字符串;

二、成員方法

  1.在String拼接中,有兩個方法,‘+’與concat方法、實現的效果一樣,不同的是concat沒有進行參數的判空,若參數為null,就會報空指針異常,其余兩個都只有append方法拼接且該拼接不會新建對象(StringBuilder,StringBuffer);

  2.StringBuilder、StringBuffer一個線程安全、一個線程不安全,其實原因也就來自於StringBuffer中append方法使用了synchronized來實現不允許多線程同時訪問;

疑惑點:

在StringBuilder、StringBuffer中其實還有一個不同點,先分別給出AbstractStringBuilder、StringBuffer、StringBuilder有關這部分的源碼

AbstractStringBuilder:

// 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;
    }

StringBuffer:

/**
     * 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:

// 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;
    }

可以看到在父類、StringBuffer都有append(StringBuffer sb)這個方法,但是卻沒有append(StringBuilder sb),只有StringBuilder有,而且還定義為private,我覺得可能這也跟StringBuilder、StringBuffer的線程安全性有關,但是想不到具體細節,留下一個疑慮點,希望知道的小夥伴能給一下答案,謝謝!

Java中String、StringBuilder、StringBuffer常用源碼分析及比較(三):String、StringBuilder、StringBuffer比較