【问题标题】:Why does StringBuffer's toString() method use Arrays.copyOfRange(value, 0, count)?为什么StringBuffer的toString()方法使用Arrays.copyOfRange(value, 0, count)?
【发布时间】:2018-12-01 16:23:04
【问题描述】:

StringBuffer的SourceCode有一个变量toStringCache,但只有在toString()方法中才会得到一个值:

public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }

为什么不使用toStringStringBuilder

return new String(value, 0, count); 

这种差异有什么特别的原因吗?

【问题讨论】:

  • 你用的是什么java版本?
  • 我不知道你为什么想知道这个,但是 StringBuilder 和 StringBuffer 之间的区别在于第一个不是线程安全的,并且在 java 1.5 中被引入作为 StringBuffer 使用时的替代品在一个线程中。我想实现差异与此有关。
  • @Aomine java1.8
  • @Juan 稍后我会看看版本记录
  • 这里有一些有用的信息 --> stackoverflow.com/questions/46294579/…

标签: java


【解决方案1】:

Java 中的字符串是不可变的,这意味着如果您只调用new String(char_array),它将生成数组的内部不可变副本。对原始 char_array 的任何更改都不会反映在新字符串中。然而,StringBuilder 正在使用包私有构造函数 String(char[] value, boolean share)。它实际上允许它使用共享数组。但是现在它必须确保这个共享数组没有被修改。所以它会制作一个副本并用它创建一个字符串。

new String(value) 也可以正常工作,但是每次调用 StringBuilder.toString() 都会创建一个新的数组副本。所以这是一个性能优化。

【讨论】:

    【解决方案2】:

    toStringCache 数组与创建的字符串共享。这样可以避免在每次 toString() 调用时复制数组内容。

    由于StringBuffer是同步的,可以保证value数组在调用过程中不会被修改,从而共享数组不会收到不一致的数据。 StringBuilder,作为非同步类,无法给予此保证。

    如果StringBuilderStringBuffer 具有相同的toString() 实现,则以下示例可能会产生输出“aa”。

    StringBuilder s = new StringBuilder("ab");
    
    // Thread A, parallel with B
    System.out.println(s.toString());
    
    // Thread B, parallel with A
    s.reverse();
    

    【讨论】:

    • 值也存储在它的超类中,是同步的
    • 正确,但假设线程 A 调用 StringBuilder.toString()。在方法返回之前,线程 B 修改了相同的StringBuilder 的内容。那么当线程A完成调用时,数组副本可能会复制不一致的状态。
    猜你喜欢
    • 2022-11-03
    • 2016-02-27
    • 2020-07-06
    • 2015-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-18
    • 1970-01-01
    相关资源
    最近更新 更多