java.lang.StringBuffer源码分析
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源码分析的更多相关文章
- java.lang.StringBuilder源码分析
StringBuilder是一个可变序列的字符数组对象,它继承自AbstractStringBuilder抽象类.它不保证同步,设计出来的目的是当这个字符串缓存只有单线程使用的时候,取代StringB ...
- java.lang.ThreadLocal源码分析
ThreadLocal类提供线程本地变量,为变量在每个线程创建一个副本,每个线程可以访问自己内部的副本变量. 比如,有这样一个需求,需要为每个线程创建一个独一无二的标识,这个标识在第一次调用Threa ...
- java.lang.Runnable 源码分析
子接口:RunnableFuture<V>, RunnableScheduledFuture<V> 实现类:AsyncBoxView.ChildState, ForkJoinW ...
- Java split方法源码分析
Java split方法源码分析 public String[] split(CharSequence input [, int limit]) { int index = 0; // 指针 bool ...
- 【JAVA】ThreadLocal源码分析
ThreadLocal内部是用一张哈希表来存储: static class ThreadLocalMap { static class Entry extends WeakReference<T ...
- 【Java】HashMap源码分析——常用方法详解
上一篇介绍了HashMap的基本概念,这一篇着重介绍HasHMap中的一些常用方法:put()get()**resize()** 首先介绍resize()这个方法,在我看来这是HashMap中一个非常 ...
- 【Java】HashMap源码分析——基本概念
在JDK1.8后,对HashMap源码进行了更改,引入了红黑树.在这之前,HashMap实际上就是就是数组+链表的结构,由于HashMap是一张哈希表,其会产生哈希冲突,为了解决哈希冲突,HashMa ...
- 细说并发5:Java 阻塞队列源码分析(下)
上一篇 细说并发4:Java 阻塞队列源码分析(上) 我们了解了 ArrayBlockingQueue, LinkedBlockingQueue 和 PriorityBlockingQueue,这篇文 ...
- jdk之java.lang.Integer源码理解
基本数据类型的包装类java.lang.Integer是我们频繁使用的一个系统类,那么通过一个示例反应出的几个问题来深入理解一下此类的源码. 需求:实现Integer类型的两个数值交换. packag ...
随机推荐
- Atom远程连接服务器报错服务器版本和客户端版本不一致
Atom远程连接服务器 报错信息: Server version is different than client version Original error message: Version mi ...
- Microsoft PetShop 集锦
一.pet shop 2.0 项目概述与架构分析微软刚推出了基于ASP.NET 2.0下的Pet Shop 4, 该版本有了一个全新的用户界面.是研究ASP.NET 2.0的好范例啊 PetShop ...
- Java 判断是否为汉字 判断是否为乱码 判断字符串是否为双整型数字 整数 数字
/** * 判断是否为汉字 * * @param str * @return */ public static boolean isGBK(String str) { char[] ch ...
- Matplotlib 工具包 使用教程索引
官方文档链接中: http://matplotlib.org/gallery.html 这里给了非常多演示样例图片.能够查看对应源码,是一个非常好学习途径. matplotlib 函数API :函数A ...
- careercup-中等难度 17.3
17.3 写一个算法计算n的阶乘末尾0的个数? 解答: 首先,算出n的阶乘的结果再去计算末尾有多少个0这种方法是不可取的, 因为n的阶乘是一个非常大的数,分分种就会溢出.我们应当去分析, 是什么使n的 ...
- Input
Input Basic Input Old Input Files Please note that both Input and Request do NOT sanitize your data, ...
- iOS 并发概念浅析
在进行iOS开发过程中,我们常会遇到网络请求.复杂计算.数据存取等比较耗时的操作,如果处理不合理,将对APP的流畅度产生较大影响.除了优化APP架构,并发(concurrency)是一个常用且较好的解 ...
- android学习——popupWindow 在指定位置上的显示
先看效果图,免得浪费大家时间,看是不是想要的效果 . 直接上代码 ,核心方法. [java] view plaincopy private void showPopupWindow(View pare ...
- [置顶] Objective-C开发环境介绍以及Cocoa,以及第一个程序
Objective-C 起源与发展 Brad J. Cox designed the Objective-C language in the early 1980 . 布兰德于1980年设计的 ...
- 关于SQL语言分类
从功能上划分,SQL语言可以分为DDL,DML和DCL三大类. 事务:可以作用在DML(update.insert.delete)语句上. 1. DDL(Data Definition Languag ...