您的位置:首页 > Web前端

Java源代码分析之StringBuffer

2016-06-14 20:49 429 查看

StringBuffer源码分析

每个Java程序员基本都了解的

长度可变字符操作工具类

在多线程环境下线程安全

额,好像想不到其他的呢?

所以需要去阅读并分析源码

StringBuffer
类图,如下



可以看到
StringBuffer
继承自
AbstractStringBuilder
(实现了Appendable接口),实现了
Serializable
CharSequence
接口。

源码分析(加入自己所理解的注释)

package java.lang;   // jdk此包实现类基本都需要了解

import java.util.Arrays;

// 线程安全、字符串可变的字符操作类
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{

/**
* 最后一次修改后的缓存值(字符数组保存),只要修改了value,那么就会重置
*/
private transient char[] toStringCache;

/** 序列号, 对象序列化和反序列化需要的唯一标识版本号 */
static final long serialVersionUID = 3388685877147921107L;

/**
* 默认构造方法
*/
public StringBuffer() {
/**
*  AbstractStringBuilder(int capacity) {
*    value = new char[capacity];
*  }
*  调用父类的构造方法,默认初始化容量为capacity = 16
*  貌似看到的所有jdk中实现类涉及初始化容量的大小都为16,加上一点扩容机制(后面详细分析)
*/
super(16);
}

/**
* 带一个参数的构造方法,可以指定初始化容量
*/
public StringBuffer(int capacity) {
super(capacity);
}

/**
* 带一个参数构造方法,与前一个不同,这是指定一个String来初始化
*/
public StringBuffer(String str) {
// 这里可以注意下,指定String初始化StringBuffer的时候指定容量大小为String的长度加上16
super(str.length() + 16);
//然后追加到value中
append(str);
}

/**
* 与前一个类似
*/
public StringBuffer(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}
//获取字符数量,效率低。。。对象锁
@Override
public synchronized int length() {
return count;
}
// 获取容量,效率低。。。对象锁
@Override
public synchronized int capacity() {
return value.length;
}

// 确保容量不小于minimumCapacity
@Override
public synchronized void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > value.length) {
// 当最小容量值(传进来的参数值)大于value.length(这个其实就是容量),那么扩容
expandCapacity(minimumCapacity);
}
}

/**
* 将value数组中没有存入元素的部分去掉(类似去空格)
* 此时容量大小和size大小相等
*/
@Override
public synchronized void trimToSize() {
super.trimToSize();
//直接调用AbstractStringBuilder已经实现的方法
/*
public void trimToSize() {
if (count < value.length) {
value = Arrays.copyOf(value, count);
}
}
*/
}

/**
* 扩充字符串容量到newLength,并且用空格填充
*/
@Override
public synchronized void setLength(int newLength) {
toStringCache = null;
//调用父类函数
super.setLength(newLength);
/*
public void setLength(int newLength) {
if (newLength < 0)
throw new StringIndexOutOfBoundsException(newLength);
// 首先扩充容量(函数说明在下面)
ensureCapacityInternal(newLength);

if (count < newLength) {
Arrays.fill(value, count, newLength, '\0');// 然后扩充部分用空格填充
}

count = newLength;
}*/
// 首先扩充容量(判断是否符合扩充条件)
/*
private void ensureCapacityInternal(int minimumCapacity) {
if (minimumCapacity - value.length > 0)
expandCapacity(minimumCapacity);
}
*/
//扩充容量  value.length * 2 + 2;
/*
void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2;
if (newCapacity - minimumCapacity < 0)
newCapacity = minimumCapacity;
if (newCapacity < 0) {
//溢出,这一步基本不会发生吧,Error那就是致命错误了
if (minimumCapacity < 0) // overflow
throw new OutOfMemoryError();
//设置容量最大值
newCapacity = Integer.MAX_VALUE;
}
// 扩充容量,分配内存存储空间
value = Arrays.copyOf(value, newCapacity);
}
*/
/*
public static char[] copyOf(char[] original, int newLength) {
char[] copy = new char[newLength];
//分配内存
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
*/
}

/**
* 根据指定索引获取字符,效率慢啊。。。对象锁
*/
@Override
public synchronized char charAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
return value[index];
}

/**
* 开始看到这个确实是一脸懵逼啊,还是一步一步看吧,返回代码点(Unicode代码点)
*/
@Override
public synchronized int codePointAt(int index) {
return super.codePointAt(index);
//父类AbstractStringBuilder方法
/*
public int codePointAt(int index) {
if ((index < 0) || (index >= count)) {
throw new StringIndexOutOfBoundsException(index);
}
return Character.codePointAtImpl(value, index, count);
}
*/
/*char:java中,char类型为16位,原本用于表示一个字符。但是后来发现,16位已经不够表示所有的字符,所以后来发展出了用代码点表示字符的方法。

代码点:是指编码字符集中,字符所对应的数字。有效范围从U+0000到U+10FFFF。其中U+0000到U+FFFF为基本字符,U+10000到U+10FFFF为增补字符。

代码单元:对代码点进行编码得到的1或2个16位序列(UTF-16)。其中基本字符的代码点直接用一个相同值的代码单元表示,增补字符的代码点用两个代码单元进行编码,编码值来自U+D800到U+DFFF,这个范围内没有数字用于表示字符,因此程序可以识别出当前字符是单单元的基本字符,还是双单元的增补字符。*/
//Character静态方法
/*
static int codePointAtImpl(char[] a, int index, int limit) {
char c1 = a[index];
if (isHighSurrogate(c1) && ++index < limit) {
char c2 = a[index];
if (isLowSurrogate(c2)) {
return toCodePoint(c1, c2);
}
}
return c1;
}
*/
}

/**
* 返回前一个代码点(一个代码点可能是一个代码单元也有可能是两个代码单元)
*/
@Override
public synchronized int codePointBefore(int index) {
//Character静态方法最终提供实现
return super.codePointBefore(index);
}

/**
* 返回代码点个数
*/
@Override
public synchronized int codePointCount(int beginIndex, int endIndex) {
return super.codePointCount(beginIndex, endIndex);
//Character静态方法最终提供实现
/*
static int codePointCountImpl(char[] a, int offset, int count) {
int endIndex = offset + count;
int n = count;
for (int i = offset; i < endIndex; ) {
if (isHighSurrogate(a[i++]) && i < endIndex &&
isLowSurrogate(a[i])) {
n--;
i++;
}
}
return n;
}*/
}

/**
* 给定初始偏移索引和代码点偏移量,返回对应索引
* 需要注意的是增补字符会用两个代码单元表示一个代码点(基本字符一个代码点对应一个代码单元),
*  一个代码单元用一个char表示,然后index索引是指char数组(value存放数据的数组)的索引
*/
@Override
public synchronized int offsetByCodePoints(int index, int codePointOffset) {
return super.offsetByCodePoints(index, codePointOffset);
// offsetByCodePoints 用法
/*
char[] ch = Character.toChars(0x10400);
String str = new String(ch);
int retval = str.offsetByCodePoints(0, 1);
System.out.println("reval = " + retval);//2
*/
}

/**
* 根据指定索引以及偏移量将字符串拷贝到dst
*/
@Override
public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,
int dstBegin)
{
super.getChars(srcBegin, srcEnd, dst, dstBegin);
//System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}

/**
* 根据索引修改字符串中某个字符值
*/
@Override
public synchronized void setCharAt(int index, char ch) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
toStringCache = null;//清除,只要修改了value,此值就会clear
value[index] = ch;
}
//追加
@Override
public synchronized StringBuffer append(Object obj) {
toStringCache = null;
super.append(String.valueOf(obj));
return this;
//父类实现AbstractStringBuilder
/*
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
//System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
count += len;
return this;
}
*/
//追加null
/*
private AbstractStringBuilder appendNull() {
int c = count;
ensureCapacityInternal(c + 4);
final char[] value = this.value;
value[c++] = 'n';
value[c++] = 'u';
value[c++] = 'l';
value[c++] = 'l';
count = c;
return this;
}
*/
}
// 同上
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}

/**
* 同上
* @since 1.4
*/
public synchronized StringBuffer append(StringBuffer sb) {
toStringCache = null;
super.append(sb);
return this;
}

/**
* @since 1.8
*/
@Override
synchronized StringBuffer append(AbstractStringBuilder asb) {
toStringCache = null;
super.append(asb);
return this;
}

/**
* 同上
* @since 1.5
*/
@Override
public synchronized StringBuffer append(CharSequence s) {
toStringCache = null;
super.append(s);
return this;
/*
public AbstractStringBuilder append(CharSequence s) {
if (s == null)
return appendNull();
if (s instanceof String)
return this.append((String)s);
if (s instanceof AbstractStringBuilder)
return this.append((AbstractStringBuilder)s);

return this.append(s, 0, s.length());
}*/
}
//同上
@Override
public synchronized StringBuffer append(CharSequence s, int start, int end)
{
toStringCache = null;
super.append(s, start, end);
return this;
}
//同上
@Override
public synchronized StringBuffer append(char[] str) {
toStringCache = null;
super.append(str);
return this;
}

//同上
@Override
public synchronized StringBuffer append(char[] str, int offset, int len) {
toStringCache = null;
super.append(str, offset, len);
return this;
}
//同上
@Override
public synchronized StringBuffer append(boolean b) {
toStringCache = null;
super.append(b);
return this;
/*
public AbstractStringBuilder append(boolean b) {
if (b) {
ensureCapacityInternal(count + 4);
value[count++] = 't';
value[count++] = 'r';
value[count++] = 'u';
value[count++] = 'e';
} else {
ensureCapacityInternal(count + 5);
value[count++] = 'f';
value[count++] = 'a';
value[count++] = 'l';
value[count++] = 's';
value[count++] = 'e';
}
return this;
}*/
}

//同上
@Override
public synchronized StringBuffer append(char c) {
toStringCache = null;
super.append(c);
return this;
}
//同上
@Override
public synchronized StringBuffer append(int i) {
toStringCache = null;
super.append(i);
return this;
}

/**
* 明白了之前分析的代码点以及代码单元,这个就没啥分析的,很容易理解
*/
@Override
public synchronized StringBuffer appendCodePoint(int codePoint) {
toStringCache = null;
super.appendCodePoint(codePoint);
return this;
/*
public AbstractStringBuilder appendCodePoint(int codePoint) {
final int count = this.count;

if (Character.isBmpCodePoint(codePoint)) {
ensureCapacityInternal(count + 1);
value[count] = (char) codePoint;
this.count = count + 1;
} else if (Character.isValidCodePoint(codePoint)) {
ensureCapacityInternal(count + 2);
Character.toSurrogates(codePoint, value, count);
this.count = count + 2;
} else {
throw new IllegalArgumentException();
}
return this;
}*/
}

@Override
public synchronized StringBuffer append(long lng) {
toStringCache = null;
super.append(lng);
return this;
}

@Override
public synchronized StringBuffer append(float f) {
toStringCache = null;
super.append(f);
return this;
}

@Override
public synchronized StringBuffer append(double d) {
toStringCache = null;
super.append(d);
return this;
}

/**
*  删除字符
*/
@Override
public synchronized StringBuffer delete(int start, int end) {
toStringCache = null;
super.delete(start, end);
// 实现:左移
//System.arraycopy(value, start+len, value, start, count-end);
return this;
}

/**
* 同上
*/
@Override
public synchronized StringBuffer deleteCharAt(int index) {
toStringCache = null;
super.deleteCharAt(index);
return this;
}

/**
* 同上
*/
@Override
public synchronized StringBuffer replace(int start, int end, String str) {
toStringCache = null;
super.replace(start, end, str);
return this;
}

/**
* 不存在内存泄漏
*/
@Override
public synchronized String substring(int start) {
return substring(start, count);
//new String(value, start, end - start);
// 没有复用char[]
}

/**
* 同上
*/
@Override
public synchronized CharSequence subSequence(int start, int end) {
return super.substring(start, end);
}

/**
* 同上
*/
@Override
public synchronized String substring(int start, int end) {
return super.substring(start, end);
}

/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @since      1.2
*/
@Override
public synchronized StringBuffer insert(int index, char[] str, int offset,
int len)
{
toStringCache = null;
super.insert(index, str, offset, len);
// System.arraycopy(value, index, value, index + len, count - index);
// System.arraycopy(str, offset, value, index, len);
return this;
}

/**
* 同上
*/
@Override
public synchronized StringBuffer insert(int offset, Object obj) {
toStringCache = null;
super.insert(offset, String.valueOf(obj));
return this;
}

/**
* 同上
*/
@Override
public synchronized StringBuffer insert(int offset, String str) {
toStringCache = null;
super.insert(offset, str);
return this;
}

/**
* 同上
*/
@Override
public synchronized StringBuffer insert(int offset, char[] str) {
toStringCache = null;
super.insert(offset, str);
return this;
}

/**
* 同上
* 此方法不同步, 而且也没有 toStringCache = null;
* 如果需要同步,那么需要将CharSequence s转化为specific type特定类型
* @since      1.5
*/
@Override
public StringBuffer insert(int dstOffset, CharSequence s) {
super.insert(dstOffset, s);
return this;
}

/**
* 同上
*/
@Override
public synchronized StringBuffer insert(int dstOffset, CharSequence s,
int start, int end)
{
toStringCache = null;
super.insert(dstOffset, s, start, end);
return this;
}

/**
* 同上
* 此方法不同步, 而且也没有 toStringCache = null;
* 如果需要同步,那么需要将boolean b转化为specific type特定类型(String)
* @since      1.5
*/
@Override
public  StringBuffer insert(int offset, boolean b) {
super.insert(offset, b);
return this;
}

/**
* 同上
*/
@Override
public synchronized StringBuffer insert(int offset, char c) {
toStringCache = null;
super.insert(offset, c);
return this;
}

/**
* 同上
* 此方法不同步, 而且也没有 toStringCache = null;
* 如果需要同步,那么需要将int i转化为specific type特定类型(String)
* @since      1.5
*/
@Override
public StringBuffer insert(int offset, int i) {
super.insert(offset, i);
return this;
}

/**
* 同上
* 此方法不同步, 而且也没有 toStringCache = null;
* 如果需要同步,那么需要将long l转化为specific type特定类型(String)
* @since      1.5
*/
@Override
public StringBuffer insert(int offset, long l) {
super.insert(offset, l);
return this;
}

/**
* 同上
* 此方法不同步, 而且也没有 toStringCache = null;
* 如果需要同步,那么需要将float f转化为specific type特定类型(String)
* @since      1.5
*/
@Override
public StringBuffer insert(int offset, float f) {
super.insert(offset, f);
return this;
}

/**
* 同上
*/
@Override
public StringBuffer insert(int offset, double d) {
super.insert(offset, d);
return this;
}

/**
* 非线程安全
*/
@Override
public int indexOf(String str) {
return super.indexOf(str);
}

/**
* 同上,但是线程安全
*/
@Override
public synchronized int indexOf(String str, int fromIndex) {
return super.indexOf(str, fromIndex);
}

/**
* 调用下面一个方法,从而保证了线程安全了
*/
@Override
public int lastIndexOf(String str) {
return lastIndexOf(str, count);
}

/**
* @since      1.4
*/
@Override
public synchronized int lastIndexOf(String str, int fromIndex) {
return super.lastIndexOf(str, fromIndex);
}

/**
* 反转
*/
@Override
public synchronized StringBuffer reverse() {
toStringCache = null;
super.reverse();
return this;
/*
public AbstractStringBuilder reverse() {
boolean hasSurrogates = false;
int n = count - 1;
//首先 收尾对调,达到反转的效果
for (int j = (n-1) >> 1; j >= 0; j--) {
int k = n - j;
char cj = value[j];
char ck = value[k];
value[j] = ck;
value[k] = cj;
if (Character.isSurrogate(cj) ||
Character.isSurrogate(ck)) {
hasSurrogates = true;
}
}
// 考虑到存在增补字符,需要成对校验
if (hasSurrogates) {
reverseAllValidSurrogatePairs();
}
return this;
}*/
}
//toStringCache之前都不知道这个字段的含义,看到这里似乎看懂了,。是提高toString函数的效率,不用每次都是 调用
//  Arrays.copyOfRange。。。但是字符串修改后这个值得clear
//线程安全
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}

// 自定义序列化字段
//**transient 用于指定哪个字段不被默认序列化,如public transient int a;
//serialPersistentFields 用于指定哪些字段需要被默认序列化.如下:
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),
};

/**
*  序列化大到ObjectOutputStream
*/
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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: