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

看这篇随笔之前请务必先看前面两章:

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的线程安全性有关,但是想不到具体细节,留下一个疑虑点,希望知道的小伙伴能给一下答案,谢谢!

posted on 2017-10-04 13:43  T~Z  阅读(283)  评论(0编辑  收藏  举报