Java中StringBuilder
和StringBuffer
之间的差异已有详细记录,并且touched upon in StackOverflow也是如此。
基本上,StringBuilder
是StringBuffer
的非同步副本,具有几乎相同的界面,因为它旨在作为StringBuffer
的更快速替代品。它们的API实际上是相同的,它们实际上是当前JDK中相同的不可访问的抽象类的子类。
因此,我想知道的一件事就是为什么他们不是公开相关的。让两个类实现一个公共接口甚至将StringBuffer
作为StringBuilder
的子类都是有意义的,允许两个类共享代码的存在。
那么为什么这种被迫分离呢?是不是程序员不会无意中将线程安全与线程不安全的代码混合在一起?或者它只是一个设计疏忽,现在将继承到永恒的结束?
修改
为了说清楚:我可以推测为什么事情是这样的,但我希望具体提到一个实际的决定,例如:在JSR过程中。对我而言,任何可能会对某些情况产生影响的事情偶然会引起一定程度的困难。
编辑2:
这两个类实现Appendable
的事实完全让我不知所措。可能是因为该特定界面对于大多数目的而言是无用的 - 它只能附加单个字符或准备好的对象,就是这样。在大多数情况下,它不比两个类都是Object
的子类更有用。
编辑3:
嗯,以下是来自a semi-official source的确切问题的基本原理:
图书馆团队的评估:
根据设计,StringBuffer和StringBuilder没有共同点 公共超类型。它们不是替代品:一个是 错误(StringBuffer),另一个(StringBuilder)是它的 更换。
显然,在某些情况下,缺乏常见的超类型会减慢 希望从StringBuffer迁移到StringBuilder。另一面 是通过添加一个常见的超类型,我们将采取我们的错误 过去并将它们置于一个公共界面,与我们共同拥有 时间。这不仅会减缓迁移速度:它会使迁移脱轨。
答案 0 :(得分:3)
我没有JSR参考,但来自我的exp。以下是几个原因:
StringBuffer
作为StringBuilder
的子类因性能原因不是一个好主意。至于使StringBuffer
线程安全,你必须屏蔽每次调用StringBuilder
,这是很多开销。
除此之外,如果您可以直接访问类的内部,则可以进一步优化,这就是Java在{{1}上添加java.lang.concurrent
的原因apis。随着更直接的访问提供更多的优化选项。支持这一点Reference from the IBM blog
进一步补充第一点,我不认为这是一个设计疏忽,因为这两个类都是java.util.Collections.synchronized*
所以他们绝对不希望这些类被子类化。
对于相同的接口,两个类都实现相同的接口,即final
。所以他们是替补。唯一的问题是它们没有实现一个通用接口,而是三个通用接口。这是有道理的,因为没有必要有一个膨胀的界面,技术上将是当前界面的总和(Serializable, Appendable, CharSequence
)。
编辑:
Serializable, Appendable, CharSequence
和StringBuffer
相同但在任何已实现的接口中都没有。这更多地与向后兼容性有关。您想要添加一个新的api但是该接口正被许多其他类使用,因此更改接口可能不可行。这是Java人员可能做出的决定。所以我不会说这是一个错误。编辑2:
SIDE注意:需要注意的另一件事是{1.0}引入了StringBuilder
,1.5中引入了StringBuffer
。因此,两个类中但不在接口中的api将在稍后引入,而不是在创建这些类时引入。
答案 1 :(得分:2)
他们实际上都是实施Appendable
。
我不同意这是没用的。根据我的经验,StringBuilder / StringBuffer用法的很大一部分只是处理字符串(实现CharSequence
)。对于其余部分,您可以在传递之前调用String.valueOf
。
如果有另一个接口也有append(long)
等其他方法,那将会很方便。但那并不重要。
拥有一个通用接口是合理的。它们具有不同的性能和线程特性,但这对于JDK中的许多接口来说都很好。
例如,CopyOnWriteArrayList
在基于数组的线程安全列表中(它为每次写入创建一个新列表),而LinkedList
是一个非线程安全的链表。