不可变对象的缺点
Disadvantages of Immutable objects
我知道 Immutable 对象比 mutable 对象有几个优势,比如它们比 mutable 对象更容易推理,它们没有复杂的状态空间随着时间的推移而改变,我们可以自由地传递它们,它们使安全散列 table 键等 etc.So 我的问题是 immutable 对象的缺点是什么??
引用自有效Java:
The only real disadvantage of immutable classes is that they require a
separate object for each distinct value. Creating these objects can be
costly, especially if they are large. For example, suppose that you
have a million-bit BigInteger and you want to change its low-order
bit:
BigInteger moby = ...;
moby = moby.flipBit(0);
The flipBit method
creates a new BigInteger
instance, also a million bits long, that
differs from the original in only one bit. The operation requires time
and space proportional to the size of the BigInteger
. Contrast this to
java.util.BitSet
. Like BigInteger
, BitSet
represents an arbitrarily
long sequence of bits, but unlike BigInteger
, BitSet
is mutable. The
BitSet
class provides a method that allows you to change the state of
a single bit of a millionbit instance in constant time.
阅读 Item 15: Minimize mutability 上的完整项目
除了可能的性能缺陷(可能!因为随着 GC 和 HotSpot 优化的复杂性,不可变结构不一定更慢)- 一个缺陷可能是状态现在必须是贯穿整个应用程序。对于简单的应用程序或小型脚本,以这种方式维护状态的工作量可能太高,无法为您购买并发安全性。
例如考虑像 Swing 这样的 GUI 框架。完全使用不可变结构和一个主要的 "unsafe" 外循环来编写一个 GUI 框架绝对是可能的,我想这已经在 Haskell 中完成了。维护嵌套不可变状态的一些问题可以通过例如镜头来解决。但是管理所有交互(注册侦听器等)可能会涉及很多,因此您可能想要引入新的抽象,例如 functional-reactive 或 hybrid-reactive GUI。
基本上,通过全部不可变,您失去了一些 OO 的封装,当这成为一个问题时,有其他方法,例如 actor 或 STM。
我每天都使用 Scala。众所周知,不变性具有某些关键优势。然而,有时在某些情况下允许可变内容更容易。这是一个人为的例子:
var counter = 0
something.map {e =>
...
counter += 1
}
当然,我可以让映射 return 包含有效负载和计数的元组,或者如果可用的话使用 collection.size。但在这种情况下,可变计数器可以说更清晰。总的来说,我更喜欢不变性,但也允许自己做出例外。
为了回答这个问题,我会引用 Lex Spoon、Bill Venners 和 Martin Odersky 的《Scala 编程》第二版第 "Next Steps in Scala" 章第 11 条:
The Scala perspective, however, is that val and var are just two different tools in your toolbox, both useful, neither inherently evil. Scala encourages you to lean towards vals, but ultimately reach for the best tool given the job at hand.
所以我想说,就像编程语言一样,val 和 var 解决了不同的问题:没有上下文就没有 "disavantage / avantage",只有一个问题要解决,而且 val / var 的地址不同问题。
希望它有所帮助,即使它没有提供具体的优点/缺点列表!
我知道 Immutable 对象比 mutable 对象有几个优势,比如它们比 mutable 对象更容易推理,它们没有复杂的状态空间随着时间的推移而改变,我们可以自由地传递它们,它们使安全散列 table 键等 etc.So 我的问题是 immutable 对象的缺点是什么??
引用自有效Java:
The only real disadvantage of immutable classes is that they require a separate object for each distinct value. Creating these objects can be costly, especially if they are large. For example, suppose that you have a million-bit BigInteger and you want to change its low-order bit:
BigInteger moby = ...;
moby = moby.flipBit(0);
The flipBit method creates a new
BigInteger
instance, also a million bits long, that differs from the original in only one bit. The operation requires time and space proportional to the size of theBigInteger
. Contrast this tojava.util.BitSet
. LikeBigInteger
,BitSet
represents an arbitrarily long sequence of bits, but unlikeBigInteger
,BitSet
is mutable. TheBitSet
class provides a method that allows you to change the state of a single bit of a millionbit instance in constant time.
阅读 Item 15: Minimize mutability 上的完整项目
除了可能的性能缺陷(可能!因为随着 GC 和 HotSpot 优化的复杂性,不可变结构不一定更慢)- 一个缺陷可能是状态现在必须是贯穿整个应用程序。对于简单的应用程序或小型脚本,以这种方式维护状态的工作量可能太高,无法为您购买并发安全性。
例如考虑像 Swing 这样的 GUI 框架。完全使用不可变结构和一个主要的 "unsafe" 外循环来编写一个 GUI 框架绝对是可能的,我想这已经在 Haskell 中完成了。维护嵌套不可变状态的一些问题可以通过例如镜头来解决。但是管理所有交互(注册侦听器等)可能会涉及很多,因此您可能想要引入新的抽象,例如 functional-reactive 或 hybrid-reactive GUI。
基本上,通过全部不可变,您失去了一些 OO 的封装,当这成为一个问题时,有其他方法,例如 actor 或 STM。
我每天都使用 Scala。众所周知,不变性具有某些关键优势。然而,有时在某些情况下允许可变内容更容易。这是一个人为的例子:
var counter = 0
something.map {e =>
...
counter += 1
}
当然,我可以让映射 return 包含有效负载和计数的元组,或者如果可用的话使用 collection.size。但在这种情况下,可变计数器可以说更清晰。总的来说,我更喜欢不变性,但也允许自己做出例外。
为了回答这个问题,我会引用 Lex Spoon、Bill Venners 和 Martin Odersky 的《Scala 编程》第二版第 "Next Steps in Scala" 章第 11 条:
The Scala perspective, however, is that val and var are just two different tools in your toolbox, both useful, neither inherently evil. Scala encourages you to lean towards vals, but ultimately reach for the best tool given the job at hand.
所以我想说,就像编程语言一样,val 和 var 解决了不同的问题:没有上下文就没有 "disavantage / avantage",只有一个问题要解决,而且 val / var 的地址不同问题。
希望它有所帮助,即使它没有提供具体的优点/缺点列表!