【发布时间】:2011-03-25 08:36:03
【问题描述】:
有一次我研究了字符串不可变的优点,因为它可以提高内存中的性能。
谁能给我解释一下?我在网上找不到。
【问题讨论】:
-
What is meant by immutable? 的可能副本。虽然该问题的标题不一样,但它包含了一个关于优缺点的问题,至少有一个答案(由 Imagist 提供)涵盖了这一点。
标签: string immutability
有一次我研究了字符串不可变的优点,因为它可以提高内存中的性能。
谁能给我解释一下?我在网上找不到。
【问题讨论】:
标签: string immutability
不变性(对于字符串或其他类型)有很多优点:
不可变字符串也有助于避免使用字符串作为缓冲区的诱惑。 C/C++ 程序中的许多缺陷与使用裸字符数组组合或修改字符串值导致的缓冲区溢出问题有关。将字符串视为可变类型会鼓励使用更适合缓冲区操作的类型(请参阅 .NET 或 Java 中的 StringBuilder)。
【讨论】:
StringBuilder 只是减缓不可变字符串连接的一种解决方法,对于与高效堆管理系统相关的 COW 模式几乎没有什么好处。 COW 可以让您的缓冲区访问安全和同时快速。
s1 和s2 类型为String 的语言中可能会有所帮助,每个变量都应该是宇宙中任何地方的唯一引用StringRef 的单独实例,并且 s1=s2; 应作为 s1.CopyFrom(s2); 执行,而不更改 StringRef s1 所指的实例。 Java 和 .NET 语言不支持这样的概念,但 C++ 支持(至少在不必与其他 .NET 语言交互的代码中)
考虑替代方案。 Java 没有 const 限定符。如果 String 对象是可变的,那么您传递对字符串的引用的任何方法都可能具有修改字符串的副作用。不可变字符串消除了防御性副本的需要,并降低了程序错误的风险。
【讨论】:
不可变字符串的复制成本很低,因为您不需要复制所有数据 - 只需复制指向数据的引用或指针即可。
任何类型的不可变类都更容易在多个线程中使用,唯一需要的同步是销毁。
【讨论】:
也许,我的回答已经过时了,但可能有人会在这里找到新信息。
为什么Java String 是不可变的以及为什么它是好的:
【讨论】:
a) 想象一下没有使字符串不可变的 StringPool 设施,这根本不可能,因为在字符串池的情况下,一个字符串对象/文字,例如“测试”已被许多引用变量引用,因此如果其中任何一个更改值,其他人将自动受到影响,即假设
字符串 A =“测试”和字符串 B =“测试”
现在字符串 B 称为 "Test".toUpperCase() 将同一对象更改为 "TEST" ,因此 A 也将是 "TEST",这是不可取的。
b) 为什么String在Java中不可变的另一个原因是允许String缓存它的hashcode,Java中的不可变String缓存它的hash码并且每次调用String的hashcode方法时都不计算,这使得它作为hashmap key非常快.
【讨论】:
想一想坐在一个公共池上的各种字符串。字符串变量然后指向池中的位置。如果你复制一个字符串变量,original 和 copy 共享相同的字符。这些共享的效率超过了通过提取子字符串和连接来编辑字符串的低效率。
【讨论】:
从根本上说,如果一个对象或方法希望将信息传递给另一个对象或方法,有几种方法可以做到:
它可以提供对包含信息的可变对象的引用,并且接收者承诺永远不会修改。
它可能会引用一个包含数据但不关心其内容的对象。
它可以将信息存储到预期数据接收者知道的可变对象中(通常由该数据接收者提供)。
它可能会返回对包含信息的不可变对象的引用。
在这些方法中,#4 是迄今为止最简单的。在许多情况下,可变对象比不可变对象更容易使用,但是没有简单的方法可以与“不可信”代码共享可变对象中的信息,而无需先将信息复制到某个东西别的。相比之下,保存在不可变对象中的信息可以通过简单地共享该引用的副本来轻松共享。
【讨论】: