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); } }
相关文章推荐
- jQuery 菜单项切换
- 【HTML5】Canvas画布
- JSON
- js-表单
- JavaScript基础
- js文件内部导入引用js文件方法
- 【HTML5】拖放(Drag 和 drop)
- [Javascript] delete keyword
- css样式优先级示例
- 原生js写的tab切换
- HTML5 服务器发送事件(server-sent events)
- 原生js全选,反选,不选
- JQuery 封装的应用 还是注册
- 【HTML5】audio音频
- build_zone_zonelists() 初始化备用内存域链表node_zonelists
- 【HTML5】Video + DOM
- codeforce 675C Money Transfers (思维)
- node.js 回调函数
- HTML5 Web Workers
- jQuery 全选