首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么字符串在许多编程语言中是不可变的?

为什么字符串在许多编程语言中是不可变的?
EN

Stack Overflow用户
提问于 2012-03-03 14:51:49
回答 4查看 15.8K关注 0票数 64

可能重复:

Why can't strings be mutable in Java and .NET?

Why .NET String is immutable?

有几种语言可供选择,例如C#、Java和Python语言。如果它的目的是为了节省内存或提高比较等操作的效率,那么它对连接和其他修改操作有什么影响?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-03-03 14:56:13

不可变类型通常是一件好事:

  • 它们在并发方面工作得更好(你不需要锁定不能改变的东西!)
  • 它们减少了错误:可变对象很容易在你意想不到的时候被改变,这可能会引入各种奇怪的错误(“一个distance")
  • They的操作可以安全地共享(即对同一对象的多个引用)),这可以减少内存消耗并提高缓存利用率。
  • 共享还使复制成为一个非常廉价的O(1)操作,如果您必须获取可变对象的防御性副本,则复制操作将是O(n)。这是一个大问题,因为复制是一个非常常见的操作(例如,每当您想要传递参数时……)

因此,使字符串不可变是一种非常合理的语言设计选择。

有些语言(特别是像Haskell和Clojure这样的函数式语言)走得更远,几乎使所有东西都是不可变的。如果你对不变性的好处感兴趣,这个enlightening video非常值得一看。

不可变类型有几个小缺点:

创建像连接这样的更改字符串的

  • 操作的开销更大,因为您需要构造新对象。通常,连接两个不可变字符串的成本为O(n+m),但如果使用基于树的字符串数据结构(如Rope ),成本可能低至O(log (m+n))。另外,如果你真的需要连接字符串efficiently.
  • A,你可以使用特殊的工具,比如Java的StringBuilder。在一个大字符串上的小改动可能会导致需要构造一个大字符串的全新副本,这显然会增加内存消耗。但是请注意,在垃圾收集语言中,这通常不是一个大问题,因为如果不保留对旧副本的引用,旧副本将很快被垃圾回收。

但总体而言,不变性的优点远远大于次要缺点。即使你只对性能感兴趣,复制的并发优势和廉价通常会使不变的字符串比具有锁定和防御性复制的可变字符串具有更高的性能。

票数 79
EN

Stack Overflow用户

发布于 2012-03-03 15:03:34

它主要是为了防止编程错误。例如,字符串经常用作哈希表中的键。如果它们可以改变,哈希表就会被破坏。这只是一个例子,当你使用一段数据时改变了它会导致问题。安全性是另一个问题:如果在执行用户请求的操作之前检查是否允许用户访问位于给定路径的文件,则包含该路径的字符串最好不是可变的……

当你在做多线程的时候,它变得更加重要。不可变的数据可以在线程之间安全地传递,而可变的数据会造成无尽的麻烦。

基本上,不可变数据使得处理它的代码更容易推理。这就是为什么纯函数式语言试图保持所有东西都不变的原因。

票数 17
EN

Stack Overflow用户

发布于 2012-03-03 15:17:26

在Java中,不仅String,而且所有的原始包装类(Integer、Double、Character等)都是不可变的。我不确定确切的原因,但我认为这些是所有编程方案都工作的基本数据类型。如果他们改变了,事情可能会变得很疯狂。更具体地说,我将使用一个示例:假设您打开了一个到远程主机的套接字连接。主机名将是字符串,端口将是Integer。如果在建立连接后修改了这些值,该怎么办?

就性能而言,Java从一个单独的内存区(称为字面池)为这些类分配内存,而不是从堆栈或堆分配内存。文字池被编入索引,如果您使用字符串" string“两次,它们指向文字池中的同一对象。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9544182

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档