激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - Java StringBuilder和StringBuffer源碼分析

Java StringBuilder和StringBuffer源碼分析

2020-03-22 12:53然則 JAVA教程

這篇文章主要針對Java中兩個常用的操作字符串的類 StringBuilder和StringBuffer進行源碼分析,感興趣的小伙伴們可以參考一下

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

一、繼承關系

?
1
2
3
4
5
6
7
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,這個類封裝了StringBuilder和StringBuffer大部分操作的實現。

二、AbstractStringBuilder

1、變量及構造方法

?
1
2
3
4
5
6
7
8
char[] value;
int count;
AbstractStringBuilder() {
}
AbstractStringBuilder(int capacity) {
  value = new char[capacity];
}
 

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

2、擴容

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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()方法

?
1
2
3
4
5
6
7
8
9
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、構造器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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()方法

?
1
2
3
4
5
6
7
8
public StringBuilder append(String str) {
  super.append(str);
  return this;
}
public StringBuilder append(CharSequence s) {
  super.append(s);
  return this;
}

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

3、toString()

?
1
2
3
4
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修飾,如下面的方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
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如下:

?
1
2
3
4
5
6
public synchronized String toString() {
  if (toStringCache == null) {
    toStringCache = Arrays.copyOfRange(value, 0, count);
  }
  return new String(toStringCache, true);
}

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

?
1
2
3
4
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有所幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美亚洲一级 | 蜜桃视频网站在线观看 | 日韩字幕在线观看 | 成人性视频欧美一区二区三区 | 久久国产精品免费视频 | 国产理论视频在线观看 | 成人国产精品一区 | 欧美精品一区二区三区久久久 | 黄色一级片免费观看 | 国产精品久久久久久久久久三级 | 欧美日韩在线影院 | 77成人影院 | 欧日韩在线视频 | vidz 98hd| 免费a视频 | 成人午夜视频在线观看 | 久久影城 | 手机av在线电影 | 视频一区二区三区在线 | 日本搞逼视频 | 欧美一级高潮片免费的 | 特级无码毛片免费视频尤物 | 免费观看的毛片手机视频 | 亚洲免费高清 | 久久99综合久久爱伊人 | 色阁五月| 九九综合九九 | 黄色网址在线视频 | 欧美激情综合网 | 手机黄网www8xcn | 亚洲国产精品久久久久制服红楼梦 | 国产毛片在线高清视频 | 免费国产在线观看 | 在线成人免费网站 | 天天夜夜操操 | 亚洲视屏在线 | 欧美成人视 | 久草视频2 | 福利一区二区三区视频在线观看 | 蜜桃视频在线观看视频 | 久久精品欧美一区 |