1

我的应用程序创建了一个类的很多实例,比如 A 类。所有实例都包含一个字符串,其中大多数都包含相同的字符串

class A {
   String myString;
}

我知道 JVM 使“所有相等的字符串”指向只存储一次的同一个字符串。如果我的 A 实例之一的 myString 字段被覆盖,则对原始字符串的引用将替换为对新 String 值的引用,并且一切都按预期工作,就好像每个实例都有一个字符串的副本一样。

兼容的 JVM 是否需要这种行为,或者它是对 jvm 的一种改进,可能会从一个 jvm 更改为另一个,或从一个版本更改为另一个版本?
提出问题的另一种方式:在设计高度冗余(基于字符串)的数据结构时,应该只依赖写时复制机制还是建议在应用程序级别放置一些东西?

4

3 回答 3

1

另一个方面是,如果它们是动态创建的(例如,由解析器分配),您的字符串将不一样。如果空间是一个问题,请查看 String.intern() :

String a = String.valueOf('a') + "b";
String b = a.intern();
String c = "ab";
// now b == c is true
于 2012-09-02T22:01:03.153 回答
0

事实是 String 是常规对象。

String a = "test";
String b = a;

与以下内容完全相同:

StringBuffer a = new StringBuffer("test");
StringBuffer b = a;

也就是说:在这两种情况下,b 都是对 a 的第二次引用,这不是由于不可变性。

不变性开始发挥作用
因此,您总是处理指向相同数据的两个指针。现在,如果类是不可变的,您可以忘记它:没有人会在您的脚下更改您的数据,不是因为您有自己的副本,而是因为共享副本是不可变的。你甚至可以认为你有一个字符串的副本,但实际上从 String b = a; 开始就没有副本存在。对每个对象执行其操作:唯一引用的副本。

于 2012-09-03T10:23:10.267 回答
0

正如@Hot Licks 所说:字符串是不可变的,因此没有地方谈论写入时的复制。同样,当您使用可变对象时,您必须注意“写入时复制”可能在您的客户端环境中不可用。

当您创建大量对象时,另一件可能非常重要的事情。每个对象都包含几个字节的标头、指针等。如果我没记错的话,空对象大约是 20 个字节。当您谈论许多包含属性的对象时,它开始变得很重要。请注意这一点,当您测量它导致问题时,您必须在应用程序级别做一些事情(轻量级设计模式,使用流 xml 解析器等)。

于 2012-09-02T21:54:59.553 回答