不可变对象的缺点

时间:2015-12-29 09:08:21

标签: scala immutability

我知道Immutable对象提供了几个优于可变对象的优点,比它们更容易推理而不是可变对象,它们没有随时间变化的复杂状态空间,我们可以自由地传递它们,它们可以创建安全的哈希表键等等。我的问题是不可变对象的缺点是什么?

4 个答案:

答案 0 :(得分:6)

引自有效Java

  

不可变类的唯一真正缺点是它们需要一个   每个不同值的单独对象。创建这些对象即可   昂贵的,特别是如果它们很大的话。例如,假设你   拥有一百万位BigInteger,你想改变它的低阶   位:

BigInteger moby = ...; 
moby = moby.flipBit(0);
  

flipBit方法   创建一个新的BigInteger实例,也就是一百万位长   只有一位与原版不同。这项行动需要时间   和空间与BigInteger的大小成正比。对比这个   java.util.BitSet。与BigInteger一样,BitSet代表任意   长序列,但与BigInteger不同,BitSet是可变的。该   BitSet类提供了一种允许您更改状态的方法   在恒定时间内单个百万位实例。

阅读Item 15: Minimize mutability

上的完整项目

答案 1 :(得分:3)

除了可能的性能缺陷(可能!因为GC和HotSpot优化的复杂性,不可变结构不一定慢) - 一个缺点是现在必须在整个应用程序中穿过状态。对于简单的应用程序或小脚本,以这种方式维护状态的努力可能太高而无法为您提供并发安全性。

例如,想想像Swing这样的GUI框架。完全可以使用不可变结构和一个主要的“不安全”外部循环来编写GUI框架,我想这已经在Haskell中完成了。保持嵌套不可变状态的一些问题可以通过例如透镜来解决。但是管理所有交互(注册侦听器等)可能会非常复杂,因此您可能希望引入新的抽象,例如功能反应或混合反应GUI。

基本上你通过全部不可变来丢失一些OO的封装,当这成为一个问题时,有其他方法,如actor或STM。

答案 2 :(得分:1)

我每天都在与Scala合作。众所周知,不变性具有一定的关键优势。然而,有时在某些情况下允许可变内容更容易。这是一个人为的例子:

var counter = 0
something.map {e =>
  ...
  counter += 1
}

当然,我可以让地图返回带有效负载和计数的元组,或者使用collection.size(如果可用)。但在这种情况下,可变计数器可以说更清楚。一般来说,我更喜欢不变性,但也允许自己做例外。

答案 3 :(得分:1)

要回答这个问题,我会引用Scala编程,第二版,“Scala中的后续步骤”一章,第11项,Lex Spoon,Bill Venners和Martin Odersky:

  然而,Scala的观点是,val和var只是工具箱中的两个不同工具,既有用又无本性。 Scala鼓励你倾向于使用vals,但最终可以找到最好的工具。

所以我会说,就像编程语言一样,val和var解决了不同的问题:没有上下文没有“disavantage / avantage”,只有一个问题需要解决,而val / var都解决了不同的问题

希望它有所帮助,即使它没有提供具体的利弊列表!