国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java StringBuilder和StringBuffer源碼分析

wangbjun / 1801人閱讀

摘要:是可以序列化的標志。構造器可以看出,默認的容量大小為。不過這個構造器是具有包訪問權限,一般情況下是不能調用的。總結和都是可變字符串,前者線程不安全,后者線程安全。和的大部分方法均調用父類的實現。其擴容機制首先是把容量變為原來容量的倍加。

簡介

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

繼承關系
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence

public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence

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

AbstractStringBuilder 變量及構造方法
char[] value;
int count;
AbstractStringBuilder() {
}
AbstractStringBuilder(int capacity) {
    value = new char[capacity];
}
    

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

擴容
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值進行拷貝,這顯然是耗時操作

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()是最常用的方法,它有很多形式的重載。上面是其中一種,用于追加字符串。如果strnull,則會調用appendNull()方法。這個方法其實是追加了"n""u""l""l"這幾個字符。如果不是null,則首先擴容,然后調用StringgetChars()方法將str追加到value末尾。最后返回對象本身,所以append()可以連續調用。

StringBuilder

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

構造器
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對象賦初始值。

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

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

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

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

SringBuffer

StiringBufferStringBuilder類似,只不過為了實現同步,很多方法使用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被修改了這個變量會被賦值為nullStringBuffertoString如下:

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

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

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

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

總結

StringBuilderStringBuffer都是可變字符串,前者線程不安全,后者線程安全。

StringBuilderStringBuffer的大部分方法均調用父類AbstractStringBuilder的實現。其擴容機制首先是把容量變為原來容量的2倍加2。最大容量是Integer.MAX_VALUE,也就是0x7fffffff

StringBuilderStringBuffer的默認容量都是16,最好預先估計好字符串的大小避免擴容帶來的時間消耗。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/65364.html

相關文章

  • Java 字符串拼接效率分析及最佳實踐

    摘要:兩個字符串拼接直接調用性能最好。關于的其他最佳實踐用時總是把能確定不為空的變量寫在左邊,如使用判斷空串,避免空指針異常。在需要把其他對象轉換為字符串對象時,使用而不是直接調用方法,因為前者已經對空值進行檢測了,不會拋出空指針異常。 本文來源于問題 Java字符串連接最佳實踐? java連接字符串有多種方式,比如+操作符,StringBuilder.append方法,這些方法各有什么優...

    BakerJ 評論0 收藏0
  • java源碼

    摘要:集合源碼解析回歸基礎,集合源碼解析系列,持續更新和源碼分析與是兩個常用的操作字符串的類。這里我們從源碼看下不同狀態都是怎么處理的。 Java 集合深入理解:ArrayList 回歸基礎,Java 集合深入理解系列,持續更新~ JVM 源碼分析之 System.currentTimeMillis 及 nanoTime 原理詳解 JVM 源碼分析之 System.currentTimeMi...

    Freeman 評論0 收藏0
  • 淺談 Java 字符串(String, StringBuffer, StringBuilder

    摘要:與類基本相同,都是可變字符換字符串序列,不同點是是線程安全的,是線程不安全的。和區別在大部分情況下是線程安全的可變字符序列。在程序中可將字符串緩沖區安全地用于多線程。 轉載自飄過的小牛 我們先要記住三者的特征: String 字符串常量 StringBuffer 字符串變量(線程安全) StringBuilder 字符串變量(非線程安全) 一、定義 showImg(/...

    ShowerSun 評論0 收藏0
  • 為什么不建議在for循環中使用"+"進行字符串拼接

    摘要:使用可以方便的對字符串進行拼接。該方法使用進行聲明,說明是一個線程安全的方法。所以,阿里巴巴開發手冊建議循環體內,字符串的連接方式,使用的方法進行擴展。但是,還要強調的是如果不是在循環體中進行字符串拼接的話,直接使用就好了。 摘要: 學習阿里巴巴Java開發手冊。 原文:為什么阿里巴巴不建議在for循環中使用+進行字符串拼接 微信公眾號:Hollis Fundebug經授權轉載,...

    caoym 評論0 收藏0
  • 從字節碼角度看String、StringBufferStringBuilder的不同

    摘要:官方說明將一個或多個類文件進行分解。顯示靜態常量為每個類中的方法打印反匯編代碼例如字節碼指令組成。在結果的行直接進行多次的拼接看看最后編譯會是神馬的這句話是對應聲明了一個,然后每次拼接實際使用的是的方法。 Oracle官方說明: javap 將一個或多個類文件進行分解。 使用簡要說明 javap [options] classfile... options 命令行選項,詳細查看后面...

    wua_wua2012 評論0 收藏0

發表評論

0條評論

wangbjun

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<