依靠java String copy来写

时间:2012-09-02 21:39:36

标签: java copy-on-write

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

class A {
   String myString;
}

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

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

3 个答案:

答案 0 :(得分:1)

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

String a = String.valueOf('a') + "b";
String b = a.intern();
String c = "ab";
// now b == c is true

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

事实是String是常规对象。

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

完全相同:

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

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

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