为什么字符串在 Java 和 .NET 中不能是可变的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/93091/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why can't strings be mutable in Java and .NET?
提问by chrissie1
Why is it that they decided to make String
immutable in Java and .NET (and some other languages)? Why didn't they make it mutable?
为什么他们决定String
在 Java 和 .NET(以及其他一些语言)中使不可变?他们为什么不让它可变?
采纳答案by PRINCESS FLUFF
According to Effective Java, chapter 4, page 73, 2nd edition:
根据Effective Java,第 4 章,第 73 页,第 2 版:
"There are many good reasons for this: Immutable classes are easier to design, implement, and use than mutable classes. They are less prone to error and are more secure.
[...]
"Immutable objects are simple.An immutable object can be in exactly one state, the state in which it was created. If you make sure that all constructors establish class invariants, then it is guaranteed that these invariants will remain true for all time, with no effort on your part.
[...]
Immutable objects are inherently thread-safe; they require no synchronization.They cannot be corrupted by multiple threads accessing them concurrently. This is far and away the easiest approach to achieving thread safety. In fact, no thread can ever observe any effect of another thread on an immutable object. Therefore, immutable objects can be shared freely
[...]
“这有很多很好的理由:不可变类比可变类更容易设计、实现和使用。它们更不容易出错并且更安全。
[...]
"不可变对象很简单。不可变对象只能处于一种状态,即创建它时的状态。如果您确保所有构造函数都建立了类不变量,那么就可以保证这些不变量始终保持真实,没有你的努力。
[...]
不可变对象本质上是线程安全的;它们不需要同步。它们不会被多个线程同时访问它们而损坏。这无疑是实现线程安全的最简单方法。事实上,没有一个线程可以观察到另一个线程对一个不可变对象的任何影响。因此, 不可变对象可以自由共享
[...]
Other small points from the same chapter:
同一章的其他小点:
Not only can you share immutable objects, but you can share their internals.
[...]
Immutable objects make great building blocks for other objects, whether mutable or immutable.
[...]
The only real disadvantage of immutable classes is that they require a separate object for each distinct value.
您不仅可以共享不可变对象,还可以共享其内部结构。
[...]
不可变对象为其他对象提供了很好的构建块,无论是可变的还是不可变的。
[...]
不可变类的唯一真正缺点是它们需要为每个不同的值提供一个单独的对象。
回答by jsight
It's largely for security reasons. It's much harder to secure a system if you can't trust that your String
s are tamperproof.
这主要是出于安全原因。如果您不能相信您的String
s 是防篡改的,那么保护系统就会困难得多。
回答by Jorge Ferreira
There are at least two reasons.
至少有两个原因。
First - securityhttp://www.javafaq.nu/java-article1060.html
第一 - 安全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.
String 成为不可变的主要原因是安全性。看这个例子:我们有一个带登录检查的文件打开方法。我们将一个字符串传递给这个方法来处理身份验证,这是在调用传递给操作系统之前所必需的。如果 String 是可变的,则可以在操作系统从程序获取请求之前进行身份验证检查后以某种方式修改其内容,然后就可以请求任何文件。因此,如果您有权在用户目录中打开文本文件,但是当您以某种方式设法更改文件名时,您可以请求打开“passwd”文件或任何其他文件。然后可以修改文件,就可以直接登录到操作系统。
Second - Memory efficiencyhttp://hikrish.blogspot.com/2006/07/why-string-class-is-immutable.html
第二 - 内存效率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.
JVM 内部维护着“字符串池”。为了实现内存效率,JVM 将从池中引用 String 对象。它不会创建新的 String 对象。因此,每当您创建一个新的字符串文字时,JVM 都会在池中检查它是否已经存在。如果已存在于池中,只需提供对同一对象的引用或在池中创建新对象。会有很多引用指向同一个String对象,如果有人修改了值,就会影响到所有引用。所以,sun 决定让它不可变。
回答by Matt Howells
Thread safety and performance. If a string cannot be modified it is safe and quick to pass a reference around among multiple threads. If strings were mutable, you would always have to copy all of the bytes of the string to a new instance, or provide synchronization. A typical application will read a string 100 times for every time that string needs to be modified. See wikipedia on immutability.
线程安全和性能。如果无法修改字符串,则在多个线程之间传递引用是安全且快速的。如果字符串是可变的,您将始终必须将字符串的所有字节复制到新实例,或提供同步。每次需要修改字符串时,典型的应用程序都会读取该字符串 100 次。有关不变性,请参阅维基百科。
回答by Evan DiBiase
One factor is that, if String
s were mutable, objects storing String
s would have to be careful to store copies, lest their internal data change without notice. Given that String
s are a fairly primitive type like numbers, it is nice when one can treat them as if they were passed by value, even if they are passed by reference (which also helps to save on memory).
一个因素是,如果String
s 是可变的,那么存储String
s 的对象必须小心存储副本,以免它们的内部数据在没有通知的情况下发生变化。鉴于String
s 是一种类似数字的相当原始的类型,如果可以将它们视为按值传递,即使它们是按引用传递(这也有助于节省内存),那就太好了。
回答by aaronroyer
It's a trade off. String
s go into the String
pool and when you create multiple identical String
s they share the same memory. The designers figured this memory saving technique would work well for the common case, since programs tend to grind over the same strings a lot.
这是一种权衡。String
s 进入String
池中,当您创建多个相同的String
s 时,它们共享相同的内存。设计者认为这种节省内存的技术适用于普通情况,因为程序往往会在相同的字符串上进行大量磨合。
The downside is that concatenations make a lot of extra String
s that are only transitional and just become garbage, actually harming memory performance. You have StringBuffer
and StringBuilder
(in Java, StringBuilder
is also in .NET) to use to preserve memory in these cases.
缺点是串联会产生很多额外的String
s,它们只是过渡性的,只是变成垃圾,实际上损害了内存性能。在这些情况下,您可以使用StringBuffer
和StringBuilder
(在 Java 中,StringBuilder
也在 .NET 中)用于保留内存。
回答by Tom Hawtin - tackline
Immutability is good. See Effective Java. If you had to copy a String every time you passed it around, then that would be a lot of error-prone code. You also have confusion as to which modifications affect which references. In the same way that Integer has to be immutable to behave like int, Strings have to behave as immutable to act like primitives. In C++ passing strings by value does this without explicit mention in the source code.
不变性很好。请参阅有效的 Java。如果每次传递字符串时都必须复制它,那么这将是很多容易出错的代码。您还不清楚哪些修改会影响哪些引用。就像 Integer 必须不可变才能表现得像 int 一样,Strings 必须表现得像不可变才能像原语一样。在 C++ 中,按值传递字符串在源代码中没有明确提及。
回答by Tom Hawtin - tackline
String
is not a primitive type, yet you normally want to use it with value semantics, i.e. like a value.
String
不是原始类型,但您通常希望将它与值语义一起使用,即像值一样。
A value is something you can trust won't change behind your back.
If you write: String str = someExpr();
You don't want it to change unless YOU do something with str
.
价值是您可以信任的东西,不会在背后改变。如果你写:String str = someExpr();
你不希望它改变,除非你用str
.
String
as an Object
has naturally pointer semantics, to get value semantics as well it needs to be immutable.
String
由于Object
具有自然的指针语义,为了获得值语义,它需要是不可变的。
回答by Motti
The decision to have string mutable in C++ causes a lot of problems, see this excellent article by Kelvin Henney about Mad COW Disease.
在 C++ 中使用字符串可变的决定会导致很多问题,请参阅 Kelvin Henney 撰写的关于Mad COW 疾病的优秀文章。
COW = Copy On Write.
COW = 写时复制。
回答by Esko Luontola
One should really ask, "why should X be mutable?" It's better to default to immutability, because of the benefits already mentioned by Princess Fluff. It should be an exception that something is mutable.
人们真的应该问,“为什么 X 应该是可变的?” 最好默认不变性,因为绒毛公主已经提到了好处。某些东西是可变的,这应该是一个例外。
Unfortunately most of the current programming languages default to mutability, but hopefully in the future the default is more on immutablity (see A Wish List for the Next Mainstream Programming Language).
不幸的是,大多数当前的编程语言默认为可变性,但希望将来默认值更多的是不可变性(请参阅下一个主流编程语言的愿望清单)。