为什么他们决定在Java和。net(和其他一些语言)中使字符串不可变?为什么不让它变呢?


当前回答

一个因素是,如果字符串是可变的,那么存储字符串的对象必须小心地存储副本,以免它们的内部数据在没有通知的情况下发生变化。鉴于字符串是一种相当基本的类型,就像数字一样,即使它们是通过引用传递的,也可以把它们当作是按值传递的,这是很好的(这也有助于节省内存)。

其他回答

这主要是出于安全考虑。如果您不能相信您的字符串是防篡改的,那么保护系统就困难得多。

至少有两个原因。

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

The main reason why String made immutable was security. Look at this example: We have a file open method with login check. We pass a String to this method to process authentication which is necessary before the call will be passed to OS. If String was mutable it was possible somehow to modify its content after the authentication check before OS gets request from program then it is possible to request any file. So if you have a right to open text file in user directory but then on the fly when somehow you manage to change the file name you can request to open "passwd" file or any other. Then a file can be modified and it will be possible to login directly to OS.

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

JVM internally maintains the "String Pool". To achive the memory efficiency, JVM will refer the String object from pool. It will not create the new String objects. So, whenever you create a new string literal, JVM will check in the pool whether it already exists or not. If already present in the pool, just give the reference to the same object or create the new object in the pool. There will be many references point to the same String objects, if someone changes the value, it will affect all the references. So, sun decided to make it immutable.

线程安全和性能。如果一个字符串不能被修改,那么在多个线程之间传递引用是安全且快速的。如果字符串是可变的,则总是必须将字符串的所有字节复制到新实例,或者提供同步。一个典型的应用程序在每次需要修改字符串时将读取字符串100次。参见维基百科关于不变性的内容。

哇!我不敢相信这里的错误信息。不可变的字符串与安全性无关。如果某人已经可以访问正在运行的应用程序中的对象(如果你试图防止某人在你的应用程序中“入侵”字符串,就必须假设这一点),那么他们肯定有很多其他可用的黑客机会。

String的不可变性解决了线程问题,这是一个相当新颖的想法。嗯…我有一个被两个不同线程改变的对象。我如何解决这个问题?同步对对象的访问?Naawww……让我们不要让任何人改变对象——这将解决我们所有混乱的并发问题!事实上,让我们让所有对象都是不可变的,然后我们就可以从Java语言中删除synchronized结构。

The real reason (pointed out by others above) is memory optimization. It is quite common in any application for the same string literal to be used repeatedly. It is so common, in fact, that decades ago, many compilers made the optimization of storing only a single instance of a String literal. The drawback of this optimization is that runtime code that modifies a String literal introduces a problem because it is modifying the instance for all other code that shares it. For example, it would be not good for a function somewhere in an application to change the String literal "dog" to "cat". A printf("dog") would result in "cat" being written to stdout. For that reason, there needed to be a way of guarding against code that attempts to change String literals (i. e., make them immutable). Some compilers (with support from the OS) would accomplish this by placing String literal into a special readonly memory segment that would cause a memory fault if a write attempt was made.

在Java中,这被称为实习。这里的Java编译器只是遵循了编译器几十年来所做的标准内存优化。为了解决这些String字面值在运行时被修改的相同问题,Java简单地使String类不可变(即,不提供允许您更改String内容的setter)。如果字符串字面量没有发生转换,字符串就不必是不可变的。

一个因素是,如果字符串是可变的,那么存储字符串的对象必须小心地存储副本,以免它们的内部数据在没有通知的情况下发生变化。鉴于字符串是一种相当基本的类型,就像数字一样,即使它们是通过引用传递的,也可以把它们当作是按值传递的,这是很好的(这也有助于节省内存)。