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