为什么他们决定在Java和。net(和其他一些语言)中使字符串不可变?为什么不让它变呢?
当前回答
人们应该问,“为什么X应该是可变的?”最好默认为不可变,因为Princess Fluff已经提到了它的好处。它应该是一个例外,某些东西是可变的。
不幸的是,目前大多数编程语言都默认为可变性,但希望未来的默认更多地是不变性(参见下一个主流编程语言的愿望清单)。
其他回答
这主要是出于安全考虑。如果您不能相信您的字符串是防篡改的,那么保护系统就困难得多。
线程安全和性能。如果一个字符串不能被修改,那么在多个线程之间传递引用是安全且快速的。如果字符串是可变的,则总是必须将字符串的所有字节复制到新实例,或者提供同步。一个典型的应用程序在每次需要修改字符串时将读取字符串100次。参见维基百科关于不变性的内容。
不可变性与安全性并没有那么紧密的联系。为此,至少在。net中,你得到了SecureString类。
稍后编辑:在Java中,你会发现GuardedString,一个类似的实现。
实际上,字符串在java中是不可变的原因与安全性没有太大关系。主要有以下两个原因:
Thead安全:
字符串是被广泛使用的对象类型。因此,它或多或少可以保证在多线程环境中使用。字符串是不可变的,以确保在线程之间共享字符串是安全的。拥有一个不可变的字符串可以确保当线程A将字符串传递给另一个线程B时,线程B不能意外地修改线程A的字符串。
Not only does this help simplify the already pretty complicated task of multi-threaded programming, but it also helps with performance of multi-threaded applications. Access to mutable objects must somehow be synchronized when they can be accessed from multiple threads, to make sure that one thread doesn't attempt to read the value of your object while it is being modified by another thread. Proper synchronization is both hard to do correctly for the programmer, and expensive at runtime. Immutable objects cannot be modified and therefore do not need synchronization.
性能:
虽然已经提到了字符串实习,但它只代表了Java程序内存效率的一小部分提高。只有字符串字面量被存储。这意味着只有源代码中相同的字符串才会共享相同的字符串对象。如果你的程序动态地创建了相同的字符串,它们将在不同的对象中表示。
More importantly, immutable strings allow them to share their internal data. For many string operations, this means that the underlying array of characters does not need to be copied. For example, say you want to take the five first characters of String. In Java, you would calls myString.substring(0,5). In this case, what the substring() method does is simply to create a new String object that shares myString's underlying char[] but who knows that it starts at index 0 and ends at index 5 of that char[]. To put this in graphical form, you would end up with the following:
| myString |
v v
"The quick brown fox jumps over the lazy dog" <-- shared char[]
^ ^
| | myString.substring(0,5)
这使得这种操作非常便宜,O(1),因为该操作既不依赖于原始字符串的长度,也不依赖于我们需要提取的子字符串的长度。这种行为也有一些内存好处,因为许多字符串可以共享它们的底层char[]。
String不是一个基本类型,但你通常想用值语义来使用它,即像一个值。
价值观是你可以信任的东西,不会在你背后改变。 String str = someExpr(); 你不希望它改变,除非你对str做些什么。
String作为对象自然具有指针语义,为了获得值语义,它也需要是不可变的。
推荐文章
- 如何为构造函数定制Visual Studio的私有字段生成快捷方式?
- 为什么Visual Studio 2015/2017/2019测试运行器没有发现我的xUnit v2测试
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- Printf与std::字符串?
- AppSettings从.config文件中获取值
- 在Jar文件中运行类
- 带参数的可运行?
- 如何检查IEnumerable是否为空或空?
- 不区分大小写的“in”
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 没有ListBox。SelectionMode="None",是否有其他方法禁用列表框中的选择?
- 我可以在Java中设置enum起始值吗?