8

StringBuilderJava和Java之间的差异StringBuffer有据可查,并且在 StackOverflow中也有所涉及。

基本上,StringBuilder它是 的非同步副本StringBuffer,具有几乎相同的界面,因为它旨在作为StringBuffer. 它们的 API 实际上是相同的,它们实际上是当前 JDK 中同一个不可访问抽象类的子类。

因此,我想知道的一件事是为什么它们没有公开相关。让这两个类都实现一个公共接口,甚至StringBuffer作为一个子类都是StringBuilder有意义的,允许两个类共享代码。

那么为什么要强制分离呢?是为了让程序员不会无意中将线程安全代码与线程不安全代码混为一谈吗?或者它只是一个设计疏忽,现在将被继承到永恒的尽头?

编辑:

说清楚:我可以推测为什么会这样,但我希望具体参考实际决策,例如在 JSR 过程中。对我来说,任何能说明什么是偶尔会引起一定困难的情况的事情。

编辑2:

这两个类都实现Appendable了我的想法。可能是因为该特定接口对于大多数用途来说是无用的——它只能附加一个字符或一个准备好的对象,仅此而已。在大多数情况下,它并不比两个类都是Object.

编辑 3:

好吧,这是来自半官方来源的这个问题的基本原理:

图书馆团队的评价:

根据设计,StringBuffer 和 StringBuilder 不共享公共的公共超类型。它们不是替代品:一个是错误(StringBuffer),另一个(StringBuilder)是它的替代品。

显然,在某些情况下,缺少通用超类型会减慢从 StringBuffer 到 StringBuilder 的预期迁移。另一方面,通过添加一个通用的超类型,我们将把我们过去的错误记录在一个公共界面中,以便永远与我们同在。这不仅会减慢迁移速度:还会使其脱轨。

4

2 回答 2

3

我没有 JSR 参考,但来自我的 exp。以下是几个原因:

  • StringBuffer由于性能原因,作为一个子类不是StringBuilder 一个好主意。为了使StringBuffer线程安全,您必须屏蔽每个StringBuilder开销很大的调用。

  • 除了以上几点,如果您可以直接访问类的内部,您可以进一步优化,这就是 Java 添加 api 的java.lang.concurrent原因java.util.Collections.synchronized*。由于更直接的访问为优化提供了更多选项。支持这一点参考来自 IBM 博客

  • 进一步补充第一点,我认为这不是设计疏忽,因为这两个类都final非常明确,他们不希望这些类被子类化。

  • 关于相同的接口,两个类都实现相同的接口,即Serializable, Appendable, CharSequence. 所以他们是直接替代品。唯一的问题是它们没有实现一个通用接口,而是实现了三个通用接口。这是有道理的,因为不需要一个臃肿的接口,它在技术上将是当前接口(Serializable, Appendable, CharSequence)的总和。

编辑:

  • @MatthewFlaschen 指出,有一些黑白相同StringBufferStringBuilder不在任何已实现的接口中的 API。这更多地与向后兼容性有关。您想添加一个新的 api,但该接口正在被许多其他类使用,因此更改接口可能不可行。这是 Java 人员可能做出的一个深思熟虑的决定。所以我不会说这是一个错误。

编辑2:

旁注:要注意的另一件事是StringBuffer在 1.0 和StringBuilder1.5 中引入。因此,两个类中都存在但接口中没有的 api 稍后会介绍,而不是在创建这些类时。

于 2012-03-19T03:39:55.920 回答
2

他们实际上都实现了Appendable.

我不同意这是没有用的。根据我的经验,StringBuilder/StringBuffer 的很大一部分使用只是处理字符串(实现CharSequence)。对于其余部分,您可以String.valueOf在传入之前调用。

如果有另一个接口也有其他方法,例如append(long). 但这不是必需的。

有一个通用的接口是合理的。它们具有不同的性能和线程特性,但这对于 JDK 中的许多接口来说都很好。

例如,CopyOnWriteArrayList在一个基于数组的线程安全列表中(它为每次写入创建一个新列表),whileLinkedList是一个非线程安全的链表。

于 2012-03-19T03:14:42.930 回答