Jdk1.4 和jdk1.5中的StringBuffer的不同
偶尔发现,Jdk1.4 和 jdk1.5 中的 StringBuffer有些不同,做了个简单调查toString() 方法
jdk1.4 中: StringBuffer 的 toString() 是这样实现的:
public String toString() {
return new String( this );
}
继续跟踪到 String 的构造函数: public String (StringBuffer buffer) { synchronized (buffer) { buffer.setShared(); this . value = buffer.getValue(); this . offset = 0; this . count = buffer.length(); } }
没有重新 new 内存空间,是共享的,这个时候首先想到的问题,如果 StringBuffer 变了, String 怎么办?
继续看 StringBuffer 的操做,例如 deleteCharAt ()
public synchronized StringBuffer deleteCharAt( int index) { if ((index < 0) || (index >= count )) throw new StringIndexOutOfBound***ception(); if ( shared ) copy(); System.arraycopy( value , index+1, value , index, count -index-1); count --; return this ; }
当 StringBuffer 改变的时候 , 判断了是否 shared, 然後决定是否 copy
而且为了避免同步问题,把方法做成同步的
jdk1.5 :
public synchronized String toString() { return new String( value , 0, count ); }
跟踪进入 String
public String( char value[], int offset, int count) { if (offset < 0) { throw new StringIndexOutOfBound***ception(offset); } if (count < 0) { throw new StringIndexOutOfBound***ception(count); } // Note: offset or count might be near -1>>>1. if (offset > value. length - count) { throw new StringIndexOutOfBound***ception(offset + count); } char [] v = new char ; System.arraycopy(value, offset, v, 0, count); this . offset = 0; this . count = count; this . value = v; } 重新分配了内存空间。
再来看看 StringBuffer 的 deleteCharAt
public synchronized StringBuffer deleteCharAt( int index) { super .deleteCharAt(index); return this ; }
有了继承关系,先不管,继续
public AbstractStringBuilder deleteCharAt( int index) { if ((index < 0) || (index >= count )) throw new StringIndexOutOfBound***ception(index); System.arraycopy( value , index+1, value , index, count -index-1); count --; return this ; }
不需要判断,也不需要 copy 了
[ 本帖最后由 hexq 于 2006-12-7 12:14 编辑 ] 既然看到了继承关系,那我们先看一下这个继承关系,再得出结论
发现
abstract class AbstractStringBuilder implements Appendable, CharSequence
然後
public final class StringBufferextends AbstractStringBuilderimplements java.io.Serializable, CharSequence
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence
看一下 document 的解释
StringBuffer 线 程安全的可 变 字符序列。
StringBuilder 一个可 变 的字符序列。
看一下 document 的解释现在可以大概做一下总结了:
首先 toString() 方法 1.4 是不 new 新空间的,把 new 新空间推后到 StringBuffer 再次被更改,提高了性能。
StirngBuffer 的一些方法是同步的
Jdk1.5 区别对待,加入了继承关系,加入了 StringBuilder
StringBuffer 是线程安全的,同步的方法
StringBuilder 的是线程不安全,非同步的
在同步方面 jdk1.5 提供了更多的选择。
疑问,为什么 jdk1.5 中, StringBuffer 改变了 toString() 的实现呢
暂时还没找到好的原因,大部份原因都比较牵强。
[ 本帖最后由 hexq 于 2006-12-7 12:10 编辑 ] jdk1.4 中: StringBuffer 的 toString() 是这样实现的:
public String toString() {
return new String( this );
}
jdk1.5 中: StringBuffer 的 toString() 是这样实现的:
public synchronized String toString() {
return new String(value, 0, count);
}
1.4的源码我没有去看,按楼主给出的1.4代码,差别只在1.5多了个同步语句 synchronized
String类在1.4和1.5中的实现也不一样了,那么StringBuffer在1.5中的toString方法即使按1.4的方法来实现也变得一样了。
在1.5中,String类的两个构造方法:
public String(StringBuffer buffer) {
// 一开始就来个 buffer.toString(); ,等于调用了String类的public String(char value[], int offset, int count)构造方法
String result = buffer.toString();
this.value = result.value;
this.count = result.count;
this.offset = result.offset;
}
public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBound***ception(offset);
}
if (count < 0) {
throw new StringIndexOutOfBound***ception(count);
}
// Note: offset or count might be near -1>>>1.
if (offset > value.length - count) {
throw new StringIndexOutOfBound***ception(offset + count);
}
char[] v = new char;
System.arraycopy(value, offset, v, 0, count);
this.offset = 0;
this.count = count;
this.value = v;
}
其中value是字符数组。
在1.5中,StringBuffer类里几乎全部方法都为同步方法,原因是在1.5中有了个StringBuilder类吧?!
页:
[1]