【Java】從源碼角度分析String,StringBuffer和StringBuilder

很多人都知道String是不可變的,StringBuffer和StringBuilder是可變的,那么為什么呢?

首先我們確定一個(gè)概念性問題,什么是不可變對(duì)象
什么是不可變對(duì)象:如果一個(gè)對(duì)象,在它創(chuàng)建完成之后,不能再改變它的狀態(tài),那么這個(gè)對(duì)象就是不可變的。不能改變狀態(tài)的意思是,不能改變對(duì)象內(nèi)的成員變量,包括基本數(shù)據(jù)類型的值不能改變,引用類型的變量不能指向其他的對(duì)象,引用類型指向的對(duì)象的狀態(tài)也不能改變。
String
以下是String的源碼截取
<pre>
** * The {@code String} class represents character strings. All * string literals in Java programs, such as {@code "abc"}, are
implemented as instances of this class. 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: String str = "abc";
is equivalent to:
char data[] = {'a', 'b', 'c'}; *
String str = new String(data);
</pre>
從上面我們可以知道每次對(duì)String對(duì)象的賦值,都是已經(jīng)改變了String指向的對(duì)象!所以String是不可變的!
再深層點(diǎn),我們會(huì)發(fā)現(xiàn)里面的data對(duì)象是final,所以呢。。呵呵呵
我們也可以很容易理解為什么當(dāng)用戶調(diào)用以下語(yǔ)句的時(shí)候,會(huì)生成了兩個(gè)對(duì)象。<pre>String s = new String("abc");</pre>

那么我們可以推出實(shí)際編程中String類型的使用時(shí)機(jī):常量,數(shù)據(jù)不會(huì)發(fā)生改變狀態(tài)下

StringBuffer和StringBuilder
很多文章都是把StringBuffer和StringBuilder分開來(lái)講解!我覺得這樣其實(shí)不好,他們區(qū)別其實(shí)就在于一個(gè)關(guān)鍵字:synchronized,這代表著使用StringBuffer是線程安全的,這就決定了他們之間的使用場(chǎng)景,在于多線程和單線程!所以,很簡(jiǎn)單,如果從使用效率上看,在單線程上跑,使用StringBuilder效率高于StringBuffer,多線程操作(例如網(wǎng)絡(luò)操作)就用StringBuffer吧!如果考慮到以后擴(kuò)展的可能性,則更難確定,所以我更愿意使用StringBuffer。

下面我們分析下StringBuffer和String的區(qū)別~
<pre>

  • A thread-safe, mutable sequence of characters.* A string buffer is like a {@link String}, but can be modified.
    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.
    </pre>
    <pre>public final class StringBuffer extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
    public final class StringBuilder extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
    </pre>

說(shuō)明StringBuffer是一個(gè)線程安全的可變序列!和StringBuilder一樣繼承了AbstractStringBuilder類,所以StringBuffer和StringBuilder作為Object對(duì)象是不能直接比較值的,不管你是用equals還是==,當(dāng)然==是用來(lái)比較內(nèi)存地址的,如果兩個(gè)對(duì)象引用的是同一個(gè)對(duì)象,會(huì)返回true;

繼承了AbstractStringBuilder的可變字符串序列
AbstractStringBuilder提供了對(duì)字符串的處理機(jī)制,同樣是將數(shù)據(jù)用char數(shù)組的類型保存:
<pre>
/** * 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) return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
</pre>
在append(str)函數(shù)調(diào)用的時(shí)候,首先會(huì)判斷原來(lái)用于存儲(chǔ)字符串的values的字符串?dāng)?shù)組有沒有足夠的大小來(lái)存儲(chǔ)將要新添加入StringBuilder的字符串。如果不夠用,那么就調(diào)用ensureCapacityInternal判斷是否有足夠的存儲(chǔ)空間,如果夠用,那么就直接添加進(jìn)去,如果不夠,那就調(diào)用 expandCapacity進(jìn)行字符串的擴(kuò)展操作。這是StringBuffer和StringBuilder可變的一個(gè)重要原因。

關(guān)于字符串更改用+還是append
結(jié)果是很明顯的!有一篇文章寫得不錯(cuò)<a >在Java中連接字符串時(shí)是使用+號(hào)還是使用StringBuilder</a>

喜歡就給我點(diǎn)個(gè)贊唄!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 31,764評(píng)論 18 399
  • Tip:筆者馬上畢業(yè)了,準(zhǔn)備開始 Java 的進(jìn)階學(xué)習(xí)計(jì)劃。于是打算先從 String 類的源碼分析入手,作為后面...
    石先閱讀 12,045評(píng)論 16 58
  • 相關(guān)概念 面向?qū)ο蟮娜齻€(gè)特征 封裝,繼承,多態(tài).這個(gè)應(yīng)該是人人皆知.有時(shí)候也會(huì)加上抽象. 多態(tài)的好處 允許不同類對(duì)...
    東經(jīng)315度閱讀 1,992評(píng)論 0 8
  • 哀怨期盼的眼神 似嗔似嬌的櫻桃 獨(dú)自倚門 在花開蝶舞的時(shí)節(jié) 是否 庭院深鎖太久? 是否 向往院外精彩? 又是否 等...
    相逢萍水閱讀 221評(píng)論 0 3
  • 與其管好時(shí)間,不如管好自己。的確,時(shí)間不以我們的意志為轉(zhuǎn)移,不管我們?cè)趺磳?duì)待時(shí)間,它都在一分一秒自顧自地流逝,唯獨(dú)...
    HelloToo閱讀 438評(píng)論 0 0