偶尔发现,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
StringIndexOutOfBoundsException();
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
StringIndexOutOfBoundsException(offset);
}
if
(count < 0) {
throw
new
StringIndexOutOfBoundsException(count);
}
// Note: offset or count might be near -1>>>1.
if
(offset > value.
length
- count) {
throw
new
StringIndexOutOfBoundsException(offset + count);
}
char
[] v =
new
char
[count];
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
StringIndexOutOfBoundsException(index);
System.arraycopy(
value
, index+1,
value
, index,
count
-index-1);
count
--;
return
this
;
}
不需要判断,也不需要
copy
了
既然看到了继承关系,那我们先看一下这个继承关系,再得出结论
发现
abstract
class
AbstractStringBuilder
implements
Appendable, CharSequence
然後
public
final
class
StringBuffer
extends
AbstractStringBuilder
implements
java.io.Serializable, CharSequence
public
final
class
StringBuilder
extends
AbstractStringBuilder
implements
java.io.Serializable, CharSequence
看一下
document
的解释
现在可以大概做一下总结了:
首先
toString()
方法
1.4
是不
new
新空间的,把
new
新空间推后到
StringBuffer
再次被更改,提高了性能。
StirngBuffer
的一些方法是同步的
Jdk1.5
区别对待,加入了继承关系,加入了
StringBuilder
StringBuffer
是线程安全的,同步的方法
StringBuilder
的是线程不安全,非同步的
在同步方面
jdk1.5
提供了更多的选择。
疑问,为什么
jdk1.5
中,
StringBuffer
改变了
toString()
的实现呢
暂时还没找到好的原因,大部份原因都比较牵强。