【问题标题】:Java StringBuffer doesn't change reference after extensionJava StringBuffer 在扩展后不会更改引用
【发布时间】:2019-03-02 17:29:35
【问题描述】:

来自StringBuffer docs

每个字符串缓冲区都有一个容量。只要字符串缓冲区包含的字符序列的长度不超过容量,就不需要分配新的内部缓冲区数组。如果内部缓冲区溢出,它会自动变大。

根据我的理解,这意味着如果我们对一个字符串缓冲区使用append方法并且给定字符串的长度超过了字符串缓冲区的容量,JVM会自动分配一些更大的内存给一个新的字符串缓冲区并将旧的字符串缓冲区与给定的字符串一起存储。但是,既然如此,旧的字符串缓冲区和新的字符串缓冲区怎么可能具有相同的引用,如下所示。附加的字符串大于 16 字节,因此这将强制 JVM 为新的字符串缓冲区分配一些新内存。

public class test {

    public static void main(String[] args) {

        StringBuffer sb = new StringBuffer("initial value");

        System.out.println("before: the reference is " + System.identityHashCode(sb));

        sb.append(" - this message is append through sb and this message is longer than 16 bytes");

        System.out.println("after: the reference is " + System.identityHashCode(sb));
    }
}

输出

before: the reference is 511833308
after: the reference is 511833308

【问题讨论】:

  • 您自己发布了它:“...分配一个新的 internal 缓冲区数组...” [:-) (并注意hashCode 的文档:可能或可能不被实现为对象内存地址的某个函数)

标签: java reference stringbuffer


【解决方案1】:

有一个间接层,通常是这种情况。实际的字符数据存储在char[] 对象中(通常)。相同的StringBuffer(或StringBuilder)实例将其对char[] 的引用从旧对象更改为新对象。没有新的StringBuffer

java.lang.StringBuffer(和父类)的 Java 源代码很容易获得,如果您想查看的话。

【讨论】:

  • 正如您在回答中提到的:“相同的StringBuffer 实例将其对char[] 的引用从旧对象更改为新对象”,这是否意味着附加后的引用会有所不同从附加之前的参考?但这与我得到的输出相矛盾,对吧?
  • @HongruLiu 有间接性。 StringBuffer 内部有一个引用(对char[])以及对StringBuffer 的任何引用(完全在StringBuffer 之外)。您的代码 ----> StringBuffer ----> char[]。改变的是后一个箭头(参考)。
【解决方案2】:

正如已经说过的,在附加字符串之后,StringBuffer 引用没有改变,它仍然是同一个对象。它只是分配更大的数组来存储字符。另外值得一提的是,覆盖hashCode 以返回有意义字段的哈希值是一种很好的做法,因为它可以帮助您跟踪对象的突变,但是由于StringBuffer 不会覆盖它,并且因为您调用System.identityHashCode ,它总是返回初始对象哈希,除非您将另一个 StringBuffer 实例分配给 sb 变量,否则它不会改变。最后一件事是默认的hashCode 实现不一定与对象引用相关,您不能依赖它

【讨论】:

  • 你知道有什么方法可以让我在更改 Java 前后跟踪StringBuffer真实引用吗?
  • 我想到的第一件事是在更改之前获取StringBufferString 表示,并在更改后与String 表示进行比较,但这会导致开销导致每个StringBuffer.toString() call 将创建新的String 实例。并且可能 StringBuffer 不是您所需要的。也许看看覆盖 hashCode 的 apache common langs StrBuilder 并向您展示更改
猜你喜欢
  • 1970-01-01
  • 2013-07-12
  • 2013-07-29
  • 1970-01-01
  • 2016-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多