国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

Java StringBuilder和StringBuffer源碼分析

2019-11-26 14:40:54
字體:
來源:轉載
供稿:網友

StringBuilder與StringBuffer是兩個常用的操作字符串的類。大家都知道,StringBuilder是線程不安全的,而StringBuffer是線程安全的。前者是JDK1.5加入的,后者在JDK1.0就有了。下面分析一下它們的內部實現。

一、繼承關系

public final class StringBufferextends AbstractStringBuilderimplements java.io.Serializable, CharSequencepublic final class StringBuilderextends AbstractStringBuilderimplements java.io.Serializable, CharSequence

可以看到,兩個類的繼承關系是一模一樣的。Serializable是可以序列化的標志。CharSequence接口包含了charAt()、length() 、subSequence()、toString()這幾個方法,String類也實現了這個接口。這里的重點是抽象類AbstractStringBuilder,這個類封裝了StringBuilder和StringBuffer大部分操作的實現。

二、AbstractStringBuilder

1、變量及構造方法

char[] value;int count;AbstractStringBuilder() {}AbstractStringBuilder(int capacity) {  value = new char[capacity];}  

AbstractStringBuilder內部用一個char[]數組保存字符串,可以在構造的時候指定初始容量方法。

2、擴容

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);}

擴容的方法最終是由expandCapacity()實現的,在這個方法中首先把容量擴大為原來的容量加2,如果此時仍小于指定的容量,那么就把新的容量設為minimumCapacity。然后判斷是否溢出,如果溢出了,把容量設為Integer.MAX_VALUE。最后把value值進行拷貝,這顯然是耗時操作。

3、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,則會調用appendNull()方法。這個方法其實是追加了'n'、'u'、'l'、'l'這幾個字符。如果不是null,則首先擴容,然后調用String的getChars()方法將str追加到value末尾。最后返回對象本身,所以append()可以連續調用。

三、StringBuilder

AbstractStringBuilder已經實現了大部分需要的方法,StringBuilder和StringBuffer只需要調用即可。下面來看看StringBuilder的實現。

1、構造器

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默認的容量大小為16。當然也可以指定初始容量,或者以一個已有的字符序列給StringBuilder對象賦初始值。

2、append()方法

public StringBuilder append(String str) {  super.append(str);  return this;}public StringBuilder append(CharSequence s) {  super.append(s);  return this;}

append()的重載方法很多,這里隨便列舉了兩個。顯然,這里是直接調用的父類AbstractStringBuilder中的方法。

3、toString()

 public String toString() {  // Create a copy, don't share the array  return new String(value, 0, count);}

toString()方法返回了一個新的String對象,與原來的對象不共享內存。其實AbstractStringBuilder中的subString()方法也是如此。

四、SringBuffer

StiringBuffer跟StringBuilder類似,只不過為了實現同步,很多方法使用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);}

可以看到,方法前面確實加了Synchronized。
另外,在上面的append()以及setLength()方法里面還有個變量toStringCache。這個變量是用于最近一次toString()方法的緩存,任何時候只要StringBuffer被修改了這個變量會被賦值為null。StringBuffer的toString如下:

public synchronized String toString() {  if (toStringCache == null) {    toStringCache = Arrays.copyOfRange(value, 0, count);  }  return new String(toStringCache, true);}

在這個方法中,如果toStringCache為null則先緩存。最終返回的String對象有點不同,這個構造方法還有個參數true。找到String的源碼看一下:

 String(char[] value, boolean share) {  // assert share : "unshared not supported";  this.value = value;}

原來這個構造方法構造出來的String對象并沒有實際復制字符串,只是把value指向了構造參數,這是為了節省復制元素的時間。不過這個構造器是具有包訪問權限,一般情況下是不能調用的。

總結

  • StringBuilder和StringBuffer都是可變字符串,前者線程不安全,后者線程安全。
  • StringBuilder和StringBuffer的大部分方法均調用父類AbstractStringBuilder的實現。其擴容機制首先是把容量變為原來容量的2倍加2。最大容量是Integer.MAX_VALUE,也就是0x7fffffff。
  • StringBuilder和StringBuffer的默認容量都是16,最好預先估計好字符串的大小避免擴容帶來的時間消耗。

以上就是本文的全部內容,希望對大家學習Java中兩個常用的操作字符串的類StringBuilder和StringBuffer有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 桦甸市| 乡城县| 新邵县| 义马市| 平武县| 闵行区| 汉寿县| 皋兰县| 开封市| 晋中市| 耒阳市| 青神县| 米脂县| 泽州县| 喀喇| 年辖:市辖区| 苗栗县| 剑川县| 宁德市| 出国| 阳朔县| 芜湖市| 贵定县| 临沭县| 临夏市| 荆门市| 灵台县| 平利县| 昭觉县| 聊城市| 贵阳市| 马尔康县| 筠连县| 法库县| 元氏县| 白玉县| 水富县| 河北区| 涡阳县| 沾化县| 惠安县|