java面試題String,StringBuilder,StringBuffer__String

來源:互聯網
上載者:User

    

       面試的經曆中,相信大家都經常被問到這三者的區別,說到String我相信絕大多數的人都會說:"String是不可變的,final修飾的",你會看到面試官微微猥瑣一笑,接著問到:“final修飾的類就是不可變的嗎,那StringBuilder和StringBuffer不是final修飾的。”


1. 先來說說String

看下JDK1.7 String成員變數的源碼

/** * @author  Lee Boynton * @author  Arthur van Hoff * @author  Martin Buchholz * @author  Ulf Zibis * @see     java.lang.Object#toString() * @see     java.lang.StringBuffer * @see     java.lang.StringBuilder * @see     java.nio.charset.Charset * @since   JDK1.0 */public final class String    implements java.io.Serializable, Comparable<String>, CharSequence {    /** The value is used for character storage. */    private final char value[];    /** Cache the hash code for the string */    private int hash; // Default to 0    /** use serialVersionUID from JDK 1.0.2 for interoperability */    private static final long serialVersionUID = -6849794470754667710L;

可以看到String定義的成員變數value和hash,其中value是個位元組數組,而且是final修飾,這個才是String不可變的關鍵點;

JDK1.7 String的部分註解

 The Java language provides special support for the string * concatenation operator ( + ), and for conversion of * other objects to strings. String concatenation is implemented * through the <code>StringBuilder</code>(or <code>StringBuffer</code>) * class and its <code>append</code> method. * String conversions are implemented through the method * <code>toString</code>, defined by <code>Object</code> and * inherited by all classes in Java. For additional information on * string concatenation and conversion, see Gosling, Joy, and Steele, * <i>The Java Language Specification</i>.
上面解釋了java為String提供了特殊的支援,例如:String a="a";  String b="b" ;當執行String c=a+b操作時,實際上是建立一個StringBuilder對象,再通過apend()進行拼接,最後調用toStirng()產生一個新的對象給c。

String提供修改內容的方法最終都是調用new String()。看下 String的部分註解

/** * The <code>String</code> class represents character strings. All * string literals in Java programs, such as <code>"abc"</code>, are * implemented as instances of this class. * <p> * Strings are constant; their values cannot be changed after they * are created. String buffers support mutable strings. * Because String objects are immutable they can be shared. For example: * <p><blockquote><pre> *     String str = "abc"; * </pre></blockquote><p> * is equivalent to: * <p><blockquote><pre> *     char data[] = {'a', 'b', 'c'}; *     String str = new String(data); * </pre></blockquote><p> * Here are some more examples of how strings can be used:

這裡定義了一個String str = "abc";相當於char data[] = {'a', 'b', 'c'};String str = new String(data);
再來看一個substring()方法的源碼


/**     * Returns a new string that is a substring of this string. The     * substring begins at the specified <code>beginIndex</code> and     * extends to the character at index <code>endIndex - 1</code>.     * Thus the length of the substring is <code>endIndex-beginIndex</code>.     * <p>     * Examples:     * <blockquote><pre>     * "hamburger".substring(4, 8) returns "urge"     * "smiles".substring(1, 5) returns "mile"     * </pre></blockquote>     *     * @param      beginIndex   the beginning index, inclusive.     * @param      endIndex     the ending index, exclusive.     * @return     the specified substring.     * @exception  IndexOutOfBoundsException  if the     *             <code>beginIndex</code> is negative, or     *             <code>endIndex</code> is larger than the length of     *             this <code>String</code> object, or     *             <code>beginIndex</code> is larger than     *             <code>endIndex</code>.     */    public String substring(int beginIndex, int endIndex) {        if (beginIndex < 0) {            throw new StringIndexOutOfBoundsException(beginIndex);        }        if (endIndex > value.length) {            throw new StringIndexOutOfBoundsException(endIndex);        }        int subLen = endIndex - beginIndex;        if (subLen < 0) {            throw new StringIndexOutOfBoundsException(subLen);        }        return ((beginIndex == 0) && (endIndex == value.length)) ? this                : new String(value, beginIndex, subLen);    }


看完這些,你可以清楚的知道定義一個變數str="hello world",則是在記憶體中分配一個對象new String("hello world"),當你修改str="hello nimei",變數重新指向記憶體中新分配的new String("hello nimei");原來記憶體中的new String("hello world")還在那裡,沒有改變,等待記憶體回收。難道真的沒有辦法修改new String("hello world")對象中的值而不重新在記憶體中重新new一次嗎。讓我們來看看一個例子。



原來通過反射可以修改String對象中的內容,反射太強大了。


2.StringBuffer和StringBuilder


StringBuffer的部分源碼

* @author      Arthur van Hoff * @see     java.lang.StringBuilder * @see     java.lang.String * @since   JDK1.0 */ public final class StringBuffer    extends AbstractStringBuilder    implements java.io.Serializable, CharSequence{    /** use serialVersionUID from JDK 1.0.2 for interoperability */    static final long serialVersionUID = 3388685877147921107L;    /**     * Constructs a string buffer with no characters in it and an     * initial capacity of 16 characters.     */    public StringBuffer() {        super(16);    }    /**     * Constructs a string buffer with no characters in it and     * the specified initial capacity.     *     * @param      capacity  the initial capacity.     * @exception  NegativeArraySizeException  if the <code>capacity</code>     *               argument is less than <code>0</code>.     */    public StringBuffer(int capacity) {        super(capacity);    }    /**     * Constructs a string buffer initialized to the contents of the     * specified string. The initial capacity of the string buffer is     * <code>16</code> plus the length of the string argument.     *     * @param   str   the initial contents of the buffer.     * @exception NullPointerException if <code>str</code> is <code>null</code>     */    public StringBuffer(String str) {        super(str.length() + 16);        append(str);    }


StringBuilder的部分源碼

* @author      Michael McCloskey * @see         java.lang.StringBuffer * @see         java.lang.String * @since       1.5 */public final class StringBuilder    extends AbstractStringBuilder    implements java.io.Serializable, CharSequence{    /** use serialVersionUID for interoperability */    static final long serialVersionUID = 4383685877147921099L;    /**     * 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);    }


StringBuffer和StringBuilder的這部分源碼基本一樣,建構函式初始化大小都為16,都是繼承了AbstractStringBuilder。


看看AbstractStringBuilder定義成員變數的源碼

/** * A mutable sequence of characters. * <p> * Implements a modifiable string. At any point in time it contains some * particular sequence of characters, but the length and content of the * sequence can be changed through certain method calls. * * @author      Michael McCloskey * @author      Martin Buchholz * @author      Ulf Zibis * @since       1.5 */abstract class AbstractStringBuilder implements Appendable, CharSequence {    /**     * 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];    }


AbstractStringBuilder中定義的變數value,是個位元組數組,和String的成員變數value相比,String的value是final修飾的,所以StringBuffer和StringBuilde的內容可以變。


在對比下StingBuffer和StringBuilder的實現其他細節,以append()方法為例。

 public synchronized StringBuffer append(String str) {        super.append(str);        return this;    }

  public StringBuilder append(String str) {        super.append(str);        return this;    }
兩者最大的區別是:StingBuffer所有的實現的方法都是sychronized修飾的,StringBuilder則不是。

2.String、StringBuffer和StringBuilder的總結
1).  String和StringBuffer、StringBuilder相比,String是不可變的,String的每次修改操作都是在記憶體中重新new一個對象出來,而StringBuffer、StringBuilder則不用,並且提供了一定的緩衝功能,預設16個位元組數組的大小,超過預設的數組長度時,則擴容為原來位元組數組的長度*2+2。
2).  StringBuffer和StringBuilder相比,StringBuffer是synchronized的,是安全執行緒的,而StringBuilder是非安全執行緒的,單線程情況下效能更好一點;使用StringBuffer和StringBuilder時,可以適當考慮下初始化大小,較少擴容的次數,提高代碼的高效性。




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.