为什么字符串在 Java 和 .NET 中不能可变?

2022-08-31 06:12:59

为什么他们决定在Java和.NET(以及其他一些语言)中实现不可变?他们为什么不让它变得可变?String


答案 1

根据 Effective Java,第 4 章,第 73 页,第 2 版:

“这有很多很好的理由:不可变类比可变类更容易设计、实现和使用。它们不易出错,更安全。

[...]

"不可变对象很简单。不可变对象可以只处于一种状态,即创建它的状态。如果您确保所有构造函数都建立了类不变量,则可以保证这些不变量将始终保持为真,而无需您付出任何努力。

[...]

不可变对象本质上是线程安全的;它们不需要同步。它们不能被多个线程同时访问它们所破坏。这无疑是实现螺纹安全性的最简单方法。事实上,没有线程可以观察到另一个线程对不可变对象的任何影响。因此,不可变对象可以自由共享

[...]

同一章中的其他小点:

您不仅可以共享不可变对象,还可以共享其内部。

[...]

不可变对象为其他对象(无论是可变对象还是不可变对象)提供了很好的构建块。

[...]

不可变类的唯一真正缺点是它们需要为每个不同的值使用单独的对象。


答案 2

至少有两个原因。

一、安全 http://www.javafaq.nu/java-article1060.html

String使不可变的主要原因是安全性。看看这个例子:我们有一个带有登录检查的文件打开方法。我们将 String 传递给此方法以处理身份验证,这是在将调用传递到操作系统之前所必需的。如果 String 是可变的,则在操作系统从程序获取请求之前,可以在身份验证检查后以某种方式修改其内容,然后可以请求任何文件。因此,如果您有权在用户目录中打开文本文件,但是当您以某种方式设法更改文件名时,您可以请求打开“passwd”文件或任何其他文件。然后可以修改文件,并且可以直接登录到操作系统。

第二 - 内存效率 http://hikrish.blogspot.com/2006/07/why-string-class-is-immutable.html

JVM 在内部维护“字符串池”。为了实现内存效率,JVM 将从池中引用 String 对象。它不会创建新的字符串对象。因此,每当您创建新的字符串文本时,JVM 都会在池中检查它是否已经存在。如果池中已存在,则只需提供对同一对象的引用或在池中创建新对象。会有很多引用指向相同的 String 对象,如果有人更改了值,就会影响所有的引用。因此,Sun决定让它变得不可变。