StringBuffer已经过时了吗?

53
在《Effective Java》这本书中,Josh Bloch说道:

StringBuffer已经过时,应该被非同步实现的StringBuilder替代。

然而,在我的实践中,我仍然看到广泛使用StringBuffer类。为什么StringBuffer类现在已经过时了?除了由于非同步带来的性能增加之外,为什么应该优先选择StringBuilder而不是StringBuffer呢?

9
你会经常看到StringBuffer的使用,其原因与你仍然经常看到Vector类的使用相同,即:1.人们阅读的是Java 1.5之前的书籍。2.在网络上仍可以找到很多使用StringBuffer的示例。3.仍有一些人在编程/教授Java时不知道StringBuilder的存在。 - helpermethod
5个回答

72

这段代码已经过时了,使用 Java 1.5 的新代码通常应该使用 StringBuilder - 真正需要以线程安全的方式构建字符串的情况非常罕见,所以为什么要承担同步成本呢?

我怀疑你看到使用 StringBuffer 的代码大多可以分为以下几类:

  • 在 Java 1.5 之前编写的
  • 为了与旧版本 JDK 兼容而编写的
  • 由不知道 StringBuilder 的人编写的
  • 由不知道 StringBuilder 的工具自动生成的

22
我查看了StringBuffer和StringBuilder的代码。它们完全相同,唯一的区别就是StringBuffer的所有方法都带有synchronized关键字。 - Varun Achar
@Varun:这一点我全然不感到惊讶。 - Jon Skeet
我怀疑很多了解StringBuilder的人仍然出于习惯而使用StringBuffer。我知道我必须克服这种习惯... - Michael Borgwardt

19

并不是每个人都像你一样广泛阅读 :-)

我只是半开玩笑。人们经常抄袭代码和模式。许多人没有关注 API 的变化。

为什么 StringBuffer 已经过时了? 因为在绝大多数情况下,它的同步行为是不必要的。 我从来没有想过需要使用它。尽管现在同步已经不再是曾经的性能问题,但在不必要的场景中支付这种代价是没有意义的。


10

为什么StringBuffer类现在已经过时了?

因为它的操作是同步的,这增加了开销并且很少有用。

你仍然看到广泛使用StringBuffer的原因只是惯性:仍然有无数的代码示例和教程没有更新为使用StringBuilder,并且人们仍然从这些来源学习过时的实践(不仅仅是这个)。即使是知道更好的人也经常回到老习惯。


5

我认为过时是一个夸张的说法。

StringBuffer是同步的,而StringBuilder则不是。

在许多情况下(也许是大多数情况下),你可能并不关心用于构建字符串的东西的线程安全性。在这些情况下应该使用StringBuilder。然而,在某些情况下,您可能确实希望确保对对象的操作是线程安全的。在这种情况下,StringBuffer仍然很有用。


3
如果您在意结果字符串中数据的顺序,我不确定是否有充分的理由使用多个线程来构建一个字符串。 - Hardwareguy
2
@硬件人:我想可能是某种记录器,因为你可以通过附加整个消息来工作。但这样会很混乱,并且代码质量不好。 - Donal Fellows

4

在大多数情况下,同步并不是必需的,如果你仍然使用它,实际上会给你的代码读者提供错误信息:即读者可能会认为需要同步,但实际上并不需要。

使用StringBuilder可以表明您不希望进行跨线程访问。

事实上,跨线程发送数据几乎总是通过明确定义的通信渠道完成,而不是简单地访问同步字符串缓冲区。因此,在某种程度上,我建议始终使用不同的解决方案,即使StringBuffer乍一看似乎是合适的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接