摘要:是可以序列化的標(biāo)志。構(gòu)造器可以看出,默認(rèn)的容量大小為。不過(guò)這個(gè)構(gòu)造器是具有包訪問(wèn)權(quán)限,一般情況下是不能調(diào)用的??偨Y(jié)和都是可變字符串,前者線程不安全,后者線程安全。和的大部分方法均調(diào)用父類的實(shí)現(xiàn)。其擴(kuò)容機(jī)制首先是把容量變?yōu)樵瓉?lái)容量的倍加。
簡(jiǎn)介
StringBuilder與StringBuffer是兩個(gè)常用的操作字符串的類。大家都知道,StringBuilder是線程不安全的,而StringBuffer是線程安全的。前者是JDK1.5加入的,后者在JDK1.0就有了。下面分析一下它們的內(nèi)部實(shí)現(xiàn)。
繼承關(guān)系public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence
可以看到,兩個(gè)類的繼承關(guān)系是一模一樣的。Serializable是可以序列化的標(biāo)志。CharSequence接口包含了charAt()、length() 、subSequence()、toString()這幾個(gè)方法,String類也實(shí)現(xiàn)了這個(gè)接口。這里的重點(diǎn)是抽象類AbstractStringBuilder,這個(gè)類封裝了StringBuilder和StringBuffer大部分操作的實(shí)現(xiàn)。
AbstractStringBuilder 變量及構(gòu)造方法char[] value; int count; AbstractStringBuilder() { } AbstractStringBuilder(int capacity) { value = new char[capacity]; }
AbstractStringBuilder內(nèi)部用一個(gè)char[]數(shù)組保存字符串,可以在構(gòu)造的時(shí)候指定初始容量方法。
擴(kuò)容public void ensureCapacity(int minimumCapacity) { if (minimumCapacity > 0) ensureCapacityInternal(minimumCapacity); } private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code if (minimumCapacity - value.length > 0) expandCapacity(minimumCapacity); } void expandCapacity(int minimumCapacity) { int newCapacity = value.length * 2 + 2; if (newCapacity - minimumCapacity < 0) newCapacity = minimumCapacity; if (newCapacity < 0) { if (minimumCapacity < 0) // overflow throw new OutOfMemoryError(); newCapacity = Integer.MAX_VALUE; } value = Arrays.copyOf(value, newCapacity); }
擴(kuò)容的方法最終是由expandCapacity()實(shí)現(xiàn)的,在這個(gè)方法中首先把容量擴(kuò)大為原來(lái)的容量加2,如果此時(shí)仍小于指定的容量,那么就把新的容量設(shè)為minimumCapacity。然后判斷是否溢出,如果溢出了,把容量設(shè)為Integer.MAX_VALUE。最后把value值進(jìn)行拷貝,這顯然是耗時(shí)操作。
append()方法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; }
append()是最常用的方法,它有很多形式的重載。上面是其中一種,用于追加字符串。如果str是null,則會(huì)調(diào)用appendNull()方法。這個(gè)方法其實(shí)是追加了"n"、"u"、"l"、"l"這幾個(gè)字符。如果不是null,則首先擴(kuò)容,然后調(diào)用String的getChars()方法將str追加到value末尾。最后返回對(duì)象本身,所以append()可以連續(xù)調(diào)用。
StringBuilderAbstractStringBuilder已經(jīng)實(shí)現(xiàn)了大部分需要的方法,StringBuilder和StringBuffer只需要調(diào)用即可。下面來(lái)看看StringBuilder的實(shí)現(xiàn)。
構(gòu)造器public StringBuilder() { super(16); } public StringBuilder(int capacity) { super(capacity); } public StringBuilder(String str) { super(str.length() + 16); append(str); } public StringBuilder(CharSequence seq) { this(seq.length() + 16); append(seq); }
可以看出,StringBuilder默認(rèn)的容量大小為16。當(dāng)然也可以指定初始容量,或者以一個(gè)已有的字符序列給StringBuilder對(duì)象賦初始值。
append()方法public StringBuilder append(String str) { super.append(str); return this; } public StringBuilder append(CharSequence s) { super.append(s); return this; }
append()的重載方法很多,這里隨便列舉了兩個(gè)。顯然,這里是直接調(diào)用的父類AbstractStringBuilder中的方法。
toString()public String toString() { // Create a copy, don"t share the array return new String(value, 0, count); }
toString()方法返回了一個(gè)新的String對(duì)象,與原來(lái)的對(duì)象不共享內(nèi)存。其實(shí)AbstractStringBuilder中的subString()方法也是如此。
SringBufferStiringBuffer跟StringBuilder類似,只不過(guò)為了實(shí)現(xiàn)同步,很多方法使用lSynchronized修飾,如下面的方法:
public synchronized int length() { return count; } public synchronized StringBuffer append(String str) { toStringCache = null; super.append(str); return this; } public synchronized void setLength(int newLength) { toStringCache = null; super.setLength(newLength); }
可以看到,方法前面確實(shí)加了Synchronized。
另外,在上面的append()以及setLength()方法里面還有個(gè)變量toStringCache。這個(gè)變量是用于最近一次toString()方法的緩存,任何時(shí)候只要StringBuffer被修改了這個(gè)變量會(huì)被賦值為null。StringBuffer的toString如下:
public synchronized String toString() { if (toStringCache == null) { toStringCache = Arrays.copyOfRange(value, 0, count); } return new String(toStringCache, true); }
在這個(gè)方法中,如果toStringCache為null則先緩存。最終返回的String對(duì)象有點(diǎn)不同,這個(gè)構(gòu)造方法還有個(gè)參數(shù)true。找到String的源碼看一下:
String(char[] value, boolean share) { // assert share : "unshared not supported"; this.value = value; }
原來(lái)這個(gè)構(gòu)造方法構(gòu)造出來(lái)的String對(duì)象并沒(méi)有實(shí)際復(fù)制字符串,只是把value指向了構(gòu)造參數(shù),這是為了節(jié)省復(fù)制元素的時(shí)間。不過(guò)這個(gè)構(gòu)造器是具有包訪問(wèn)權(quán)限,一般情況下是不能調(diào)用的。
總結(jié)StringBuilder和StringBuffer都是可變字符串,前者線程不安全,后者線程安全。
StringBuilder和StringBuffer的大部分方法均調(diào)用父類AbstractStringBuilder的實(shí)現(xiàn)。其擴(kuò)容機(jī)制首先是把容量變?yōu)樵瓉?lái)容量的2倍加2。最大容量是Integer.MAX_VALUE,也就是0x7fffffff。
StringBuilder和StringBuffer的默認(rèn)容量都是16,最好預(yù)先估計(jì)好字符串的大小避免擴(kuò)容帶來(lái)的時(shí)間消耗。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/65364.html
摘要:兩個(gè)字符串拼接直接調(diào)用性能最好。關(guān)于的其他最佳實(shí)踐用時(shí)總是把能確定不為空的變量寫(xiě)在左邊,如使用判斷空串,避免空指針異常。在需要把其他對(duì)象轉(zhuǎn)換為字符串對(duì)象時(shí),使用而不是直接調(diào)用方法,因?yàn)榍罢咭呀?jīng)對(duì)空值進(jìn)行檢測(cè)了,不會(huì)拋出空指針異常。 本文來(lái)源于問(wèn)題 Java字符串連接最佳實(shí)踐? java連接字符串有多種方式,比如+操作符,StringBuilder.append方法,這些方法各有什么優(yōu)...
摘要:與類基本相同,都是可變字符換字符串序列,不同點(diǎn)是是線程安全的,是線程不安全的。和區(qū)別在大部分情況下是線程安全的可變字符序列。在程序中可將字符串緩沖區(qū)安全地用于多線程。 轉(zhuǎn)載自飄過(guò)的小牛 我們先要記住三者的特征: String 字符串常量 StringBuffer 字符串變量(線程安全) StringBuilder 字符串變量(非線程安全) 一、定義 showImg(/...
摘要:使用可以方便的對(duì)字符串進(jìn)行拼接。該方法使用進(jìn)行聲明,說(shuō)明是一個(gè)線程安全的方法。所以,阿里巴巴開(kāi)發(fā)手冊(cè)建議循環(huán)體內(nèi),字符串的連接方式,使用的方法進(jìn)行擴(kuò)展。但是,還要強(qiáng)調(diào)的是如果不是在循環(huán)體中進(jìn)行字符串拼接的話,直接使用就好了。 摘要: 學(xué)習(xí)阿里巴巴Java開(kāi)發(fā)手冊(cè)。 原文:為什么阿里巴巴不建議在for循環(huán)中使用+進(jìn)行字符串拼接 微信公眾號(hào):Hollis Fundebug經(jīng)授權(quán)轉(zhuǎn)載,...
摘要:官方說(shuō)明將一個(gè)或多個(gè)類文件進(jìn)行分解。顯示靜態(tài)常量為每個(gè)類中的方法打印反匯編代碼例如字節(jié)碼指令組成。在結(jié)果的行直接進(jìn)行多次的拼接看看最后編譯會(huì)是神馬的這句話是對(duì)應(yīng)聲明了一個(gè),然后每次拼接實(shí)際使用的是的方法。 Oracle官方說(shuō)明: javap 將一個(gè)或多個(gè)類文件進(jìn)行分解。 使用簡(jiǎn)要說(shuō)明 javap [options] classfile... options 命令行選項(xiàng),詳細(xì)查看后面...
閱讀 3409·2021-09-22 15:01
閱讀 535·2019-08-30 11:11
閱讀 965·2019-08-29 16:17
閱讀 1218·2019-08-29 12:23
閱讀 2036·2019-08-26 11:48
閱讀 3189·2019-08-26 11:48
閱讀 1427·2019-08-26 10:33
閱讀 1938·2019-08-26 10:30