最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java StringBuilder和StringBuffer源碼分析

 更新時(shí)間:2016年01月14日 14:15:41   作者:然則  
這篇文章主要針對(duì)Java中兩個(gè)常用的操作字符串的類(lèi) StringBuilder和StringBuffer進(jìn)行源碼分析,感興趣的小伙伴們可以參考一下

StringBuilder與StringBuffer是兩個(gè)常用的操作字符串的類(lèi)。大家都知道,StringBuilder是線(xiàn)程不安全的,而StringBuffer是線(xiàn)程安全的。前者是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è)類(lèi)的繼承關(guān)系是一模一樣的。Serializable是可以序列化的標(biāo)志。CharSequence接口包含了charAt()、length() 、subSequence()、toString()這幾個(gè)方法,String類(lèi)也實(shí)現(xiàn)了這個(gè)接口。這里的重點(diǎn)是抽象類(lèi)AbstractStringBuilder,這個(gè)類(lèi)封裝了StringBuilder和StringBuffer大部分操作的實(shí)現(xiàn)。

二、AbstractStringBuilder

1、變量及構(gòu)造方法

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

AbstractStringBuilder內(nèi)部用一個(gè)char[]數(shù)組保存字符串,可以在構(gòu)造的時(shí)候指定初始容量方法。

2、擴(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í)操作。

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

三、StringBuilder

AbstractStringBuilder已經(jīng)實(shí)現(xiàn)了大部分需要的方法,StringBuilder和StringBuffer只需要調(diào)用即可。下面來(lái)看看StringBuilder的實(shí)現(xiàn)。

1、構(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ì)象賦初始值。

2、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)用的父類(lèi)AbstractStringBuilder中的方法。

3、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()方法也是如此。

四、SringBuffer

StiringBuffer跟StringBuilder類(lèi)似,只不過(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)造器是具有包訪(fǎng)問(wèn)權(quán)限,一般情況下是不能調(diào)用的。

總結(jié)

  • StringBuilder和StringBuffer都是可變字符串,前者線(xiàn)程不安全,后者線(xiàn)程安全。
  • StringBuilder和StringBuffer的大部分方法均調(diào)用父類(lèi)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í)間消耗。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家學(xué)習(xí)Java中兩個(gè)常用的操作字符串的類(lèi)StringBuilder和StringBuffer有所幫助。

相關(guān)文章

  • Java 反射之私有字段和方法詳細(xì)介紹

    Java 反射之私有字段和方法詳細(xì)介紹

    本文將介紹Java 反射之私有字段和方法的應(yīng)用,需呀了解的朋友可以參考下
    2012-11-11
  • Java?list如何實(shí)現(xiàn)將指定元素排在第一位

    Java?list如何實(shí)現(xiàn)將指定元素排在第一位

    這篇文章主要為大家詳細(xì)介紹了Java?list中如何實(shí)現(xiàn)將指定元素排在第一位,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-02-02
  • maven package 打包報(bào)錯(cuò) Failed to execute goal的解決

    maven package 打包報(bào)錯(cuò) Failed to execute goal的解決

    這篇文章主要介紹了maven package 打包報(bào)錯(cuò) Failed to execute goal的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Java字符串操作和C#字符串操作的不同小結(jié)

    Java字符串操作和C#字符串操作的不同小結(jié)

    在JAVA語(yǔ)言中,字符串?dāng)?shù)據(jù)實(shí)際上由String類(lèi)所實(shí)現(xiàn)的。下面這篇文章主要給大家介紹了關(guān)于Java字符串操作和C#字符串操作的不同的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-12-12
  • Java輸出多位小數(shù)的三種方法(附代碼)

    Java輸出多位小數(shù)的三種方法(附代碼)

    這篇文章主要給大家介紹了關(guān)于Java輸出多位小數(shù)的三種方法的相關(guān)資料,在實(shí)際工作中常常需要設(shè)定數(shù)字的輸出格式,如以百分比的形式輸出,或者設(shè)定小數(shù)位數(shù)等,需要的朋友可以參考下
    2023-07-07
  • MyBatis測(cè)試報(bào)錯(cuò):Cannot?determine?value?type?from?string?'xxx'的解決辦法

    MyBatis測(cè)試報(bào)錯(cuò):Cannot?determine?value?type?from?string?&a

    這篇文章主要給大家介紹了關(guān)于MyBatis測(cè)試報(bào)錯(cuò):Cannot?determine?value?type?from?string?'xxx'的解決辦法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • Java?Web實(shí)現(xiàn)簡(jiǎn)易圖書(shū)管理系統(tǒng)

    Java?Web實(shí)現(xiàn)簡(jiǎn)易圖書(shū)管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Java?Web實(shí)現(xiàn)簡(jiǎn)易圖書(shū)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • 詳解spring cloud分布式關(guān)于熔斷器

    詳解spring cloud分布式關(guān)于熔斷器

    這篇文章主要介紹了詳解spring cloud分布式關(guān)于熔斷器,詳細(xì)的介紹了什么是熔斷器和使用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • 分享java中設(shè)置代理的兩種方式

    分享java中設(shè)置代理的兩種方式

    有時(shí)候我們的程序中要提供可以使用代理訪(fǎng)問(wèn)網(wǎng)絡(luò),代理的方式包括http、https、ftp、socks代理。比如在IE瀏覽器設(shè)置代理,這里簡(jiǎn)單介紹下,需要的朋友可以參考下
    2015-12-12
  • JAVASE系統(tǒng)實(shí)現(xiàn)抽卡功能

    JAVASE系統(tǒng)實(shí)現(xiàn)抽卡功能

    這篇文章主要為大家詳細(xì)介紹了JAVASE系統(tǒng)實(shí)現(xiàn)抽卡功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-11-11

最新評(píng)論

昭觉县| 兴隆县| 宁国市| 岐山县| 彭水| 大姚县| 扎兰屯市| 罗源县| 沾化县| 彭泽县| 万全县| 玛曲县| 冕宁县| 吉安县| 响水县| 阿坝| 青神县| 盱眙县| 宜川县| 潢川县| 乡宁县| 仪陇县| 盘锦市| 六盘水市| 弋阳县| 肥乡县| 双峰县| 屯门区| 忻城县| 高阳县| 兰考县| 洛南县| 禹州市| 富民县| 延庆县| 莱阳市| 金塔县| 肃宁县| 信丰县| 巨野县| 吴川市|