StringBuffer是一个线程安全的可变序列的字符数组对象,它与StringBuilder一样,继承父类AbstractStringBuilder。在多线程环境中,当方法操作是必须被同步,StringBuffer内的方法被同步化时,以实现跟在单线程中操作一样的一致性。

public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence {
//一个缓存用来存储最后一次调用toString返回的值,每当StringBuffer被修改就把该缓存清空
private transient char[] toStringCache; public StringBuffer() {
super(16);
} public StringBuffer(int capacity) {
super(capacity);
} //...more constructs,提供与父类一致的构造器,StringBuffer的构造器总是调用父类的构造器 @Override
public synchronized int length() {//返回容器中字符的数量
return count;
} @Override
public synchronized int capacity() {//返回容器的大小
return value.length;
} @Override
public synchronized void ensureCapacity(int minimumCapacity) {//保证容器足够大
if (minimumCapacity > value.length) {
expandCapacity(minimumCapacity);
}
} @Override
public synchronized void trimToSize() {//将容器的大小与容器的字符数量变成一致的
super.trimToSize();
} //setLength是修改了StringBuffer,所以要把toStringCache设置为null
public synchronized void setLength(int newLength) {
toStringCache = null;
super.setLength(newLength);
} //...append,insert方法还有其他需要同步化的方法都是覆盖父类,用synchronized使方法同步化,同时那些修改了StringBuffer的方法,需要先把toStringCache设置为null //下面几个insert方法没有用synchronized来实现同步化,上面的解释说这些方法的同步化是通过调用其他StringBuffer方法来实现的
public StringBuffer insert(int dstOffset, CharSequence s) {
// Note, synchronization achieved via invocations of other StringBuffer methods
// after narrowing of s to specific type
// Ditto for toStringCache clearing
super.insert(dstOffset, s);
return this;
} public StringBuffer insert(int offset, boolean b) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of b to String by super class method
// Ditto for toStringCache clearing
super.insert(offset, b);
return this;
} public StringBuffer insert(int offset, int i) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of i to String by super class method
// Ditto for toStringCache clearing
super.insert(offset, i);
return this;
} public StringBuffer insert(int offset, long l) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of l to String by super class method
// Ditto for toStringCache clearing
super.insert(offset, l);
return this;
} public StringBuffer insert(int offset, float f) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of f to String by super class method
// Ditto for toStringCache clearing
super.insert(offset, f);
return this;
} public StringBuffer insert(int offset, double d) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of d to String by super class method
// Ditto for toStringCache clearing
super.insert(offset, d);
return this;
} public int indexOf(String str) {
// Note, synchronization achieved via invocations of other StringBuffer methods
return super.indexOf(str);
} public int lastIndexOf(String str) {
// Note, synchronization achieved via invocations of other StringBuffer methods
return lastIndexOf(str, count);
} //这个toString方法很重要,如果toStringCache为null时,会把当前的value复制一份新的给它,否则返回String(toStringCache)
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
} //下面的三个方法是为了实现StringBuffer的序列化和反序列化
private static final java.io.ObjectStreamField[] serialPersistentFields =
{
new java.io.ObjectStreamField("value", char[].class),
new java.io.ObjectStreamField("count", Integer.TYPE),
new java.io.ObjectStreamField("shared", Boolean.TYPE),
}; private synchronized void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
java.io.ObjectOutputStream.PutField fields = s.putFields();
fields.put("value", value);
fields.put("count", count);
fields.put("shared", false);
s.writeFields();
} private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
java.io.ObjectInputStream.GetField fields = s.readFields();
value = (char[])fields.get("value", null);
count = fields.get("count", 0);
}

从上面源码可知,StringBuffer将父类非线程安全的方法都覆盖实现同步化,它自己拥有一个toStringCache的缓存,当这个缓存为空的时候,就知道StringBuffer被修改过了,这时候调用toString方法,就能得到被修改后最新的值。

java.lang.StringBuffer源码分析的更多相关文章

  1. java.lang.StringBuilder源码分析

    StringBuilder是一个可变序列的字符数组对象,它继承自AbstractStringBuilder抽象类.它不保证同步,设计出来的目的是当这个字符串缓存只有单线程使用的时候,取代StringB ...

  2. java.lang.ThreadLocal源码分析

    ThreadLocal类提供线程本地变量,为变量在每个线程创建一个副本,每个线程可以访问自己内部的副本变量. 比如,有这样一个需求,需要为每个线程创建一个独一无二的标识,这个标识在第一次调用Threa ...

  3. java.lang.Runnable 源码分析

    子接口:RunnableFuture<V>, RunnableScheduledFuture<V> 实现类:AsyncBoxView.ChildState, ForkJoinW ...

  4. Java split方法源码分析

    Java split方法源码分析 public String[] split(CharSequence input [, int limit]) { int index = 0; // 指针 bool ...

  5. 【JAVA】ThreadLocal源码分析

    ThreadLocal内部是用一张哈希表来存储: static class ThreadLocalMap { static class Entry extends WeakReference<T ...

  6. 【Java】HashMap源码分析——常用方法详解

    上一篇介绍了HashMap的基本概念,这一篇着重介绍HasHMap中的一些常用方法:put()get()**resize()** 首先介绍resize()这个方法,在我看来这是HashMap中一个非常 ...

  7. 【Java】HashMap源码分析——基本概念

    在JDK1.8后,对HashMap源码进行了更改,引入了红黑树.在这之前,HashMap实际上就是就是数组+链表的结构,由于HashMap是一张哈希表,其会产生哈希冲突,为了解决哈希冲突,HashMa ...

  8. 细说并发5:Java 阻塞队列源码分析(下)

    上一篇 细说并发4:Java 阻塞队列源码分析(上) 我们了解了 ArrayBlockingQueue, LinkedBlockingQueue 和 PriorityBlockingQueue,这篇文 ...

  9. jdk之java.lang.Integer源码理解

    基本数据类型的包装类java.lang.Integer是我们频繁使用的一个系统类,那么通过一个示例反应出的几个问题来深入理解一下此类的源码. 需求:实现Integer类型的两个数值交换. packag ...

随机推荐

  1. Atom远程连接服务器报错服务器版本和客户端版本不一致

    Atom远程连接服务器 报错信息: Server version is different than client version Original error message: Version mi ...

  2. Microsoft PetShop 集锦

    一.pet shop 2.0 项目概述与架构分析微软刚推出了基于ASP.NET 2.0下的Pet Shop 4, 该版本有了一个全新的用户界面.是研究ASP.NET 2.0的好范例啊 PetShop ...

  3. Java 判断是否为汉字 判断是否为乱码 判断字符串是否为双整型数字 整数 数字

    /**  * 判断是否为汉字  *   * @param str  * @return  */ public static boolean isGBK(String str) {  char[] ch ...

  4. Matplotlib 工具包 使用教程索引

    官方文档链接中: http://matplotlib.org/gallery.html 这里给了非常多演示样例图片.能够查看对应源码,是一个非常好学习途径. matplotlib 函数API :函数A ...

  5. careercup-中等难度 17.3

    17.3 写一个算法计算n的阶乘末尾0的个数? 解答: 首先,算出n的阶乘的结果再去计算末尾有多少个0这种方法是不可取的, 因为n的阶乘是一个非常大的数,分分种就会溢出.我们应当去分析, 是什么使n的 ...

  6. Input

    Input Basic Input Old Input Files Please note that both Input and Request do NOT sanitize your data, ...

  7. iOS 并发概念浅析

    在进行iOS开发过程中,我们常会遇到网络请求.复杂计算.数据存取等比较耗时的操作,如果处理不合理,将对APP的流畅度产生较大影响.除了优化APP架构,并发(concurrency)是一个常用且较好的解 ...

  8. android学习——popupWindow 在指定位置上的显示

    先看效果图,免得浪费大家时间,看是不是想要的效果 . 直接上代码 ,核心方法. [java] view plaincopy private void showPopupWindow(View pare ...

  9. [置顶] Objective-C开发环境介绍以及Cocoa,以及第一个程序

      Objective-C 起源与发展 Brad J. Cox designed the  Objective-C language in the early 1980 . 布兰德于1980年设计的  ...

  10. 关于SQL语言分类

    从功能上划分,SQL语言可以分为DDL,DML和DCL三大类. 事务:可以作用在DML(update.insert.delete)语句上. 1. DDL(Data Definition Languag ...