为什么StringBuffer有一个toStringCache而StringBuilder没有?

时间:2017-09-19 07:33:54

标签: java java-8 stringbuilder stringbuffer

在JDK 8中,StringBuffer类有toStringCache,而StringBuilder没有。{/ p>

/**
 * A cache of the last value returned by toString. Cleared
 * whenever the StringBuffer is modified.
 */
private transient char[] toStringCache;

但为什么?

  • 我能想到的一个可能原因是StringBuffer已经同步,因此可以更轻松地实现缓存。

  • 或者也许历史上StringBuffer是以这种方式实现的,因此旧代码在很大程度上依赖于此功能?

鉴于具有转义分析和偏向锁定的现代JVM,差异是否相关?

2 个答案:

答案 0 :(得分:5)

考虑历史背景可能会有所帮助。 Java {5}引入了StringBuilder,因为已经认识到StringBuffer不适合其实际用例。

新引入的StringBuilder是针对在纯粹的本地环境中构建,使用和立即删除的主要用例而设计的。因此,它没有提供任何同步,并且它没有考虑优化罕见的toString()方法被多次调用而没有中间更改(这在现实生活中何时发生?),事实上,在不牺牲无线程同步的性能优势的情况下提供缓存功能,介于“硬”到“不可能”之间。

虽然StringBuilder被记录为不是线程安全的,所以你知道在同时调用方法时会发生不一致的事情,类String通过不变性保证线程安全,因此,它不允许StringBuilder缺少同步可能导致已构造的字符串不一致,并且根本不在StringStringBuilder之间共享数组,这是最安全的解决方案。

那么,为什么这种优化在那里,如果它在现实生活中几乎没有任何好处?好吧,因为它存在很长一段时间,很可能甚至从Java 1.0开始,并且不值得改变类StringBuffer中的任何内容。它的存在可能没有任何真正的优势,但也没有删除它,这将需要新的测试等等,并可能成为某些应用程序的space bar overheating feature ......

你可能会注意到,在Java 1.x中,很多设计决策在今天看起来很奇怪。在基础课中过度使用synchronized就是其中之一,这几乎没有帮助优化另一个。当时,即使是不可变性的含义也没有得到很好的理解,这就是为什么我们有String.valueOf(char[])String.copyValueOf(char[])这样的冗余方法,以及使用new String(char[])的机会......

答案 1 :(得分:3)

我认为你的第一个猜测是高度准确的,因为StringBuilder不是线程安全的,并且一个实例可以在多个线程之间共享,实现这样的缓存需要额外的同步,这将失去{的目的{1}}首先。

至于为什么需要这个,它归结为使用的StringBuilder构造函数;如果new String(...)使用构造函数StringBuffer,则评论说:

  

打包私有构造函数,它为速度共享值数组。