不可变的java对象

时间:2012-07-17 10:23:33

标签: java design-patterns bigdecimal

今天我正在阅读有关BigDecimal类的一些文档, 我偶然发现了一个基本属性,BigDecimal类是不可变的。

我怎么能向祖母解释不变性概念?

班级不变性的利弊是什么?

扩展类可以变得可变吗?

考虑到我想用我的类扩展BigDecimal:

`MyBigDecimal extends BigDecimal` 

扩展是否违反了面向对象的基本设计原则?

4 个答案:

答案 0 :(得分:9)

  

我怎么能向祖母解释不变性概念?

请检查此问题:What is meant by immutable

或者来自Effective Java:

  

不可变类是无法修改其实例的类。每个实例中包含的所有信息都在创建时提供,并在对象的生命周期内得到修复。


  

班级不变性的利弊是什么?

优点:

  • 更容易推断对象的状态,因为只有一个,初始化时构建的状态
  • 推论:不可变对象在并发编程中更容易使用,其中状态就是一切

缺点:

  • 当您想要更改对象的属性时,您需要创建一个新的=昂贵的
  • 构造可能更复杂(参见构建器模式)

  

扩展类可以变得可变吗?

是 - 这就是为什么不可变类应该是最终的(或者,使所有构造函数都是私有的,并提供工厂来创建新对象)。

BigDecimal是创建不可变类时应该的一个很好的例子(它可以扩展,这可能会导致你在问题中提到的问题)。

答案 1 :(得分:3)

一个不变的类,其实例永远不会改变。对象的状态在构造时定义,之后永远不会改变。

为了正确不可变,该类不提供任何改变其状态的方法(除了反射):没有setter方法,没有改变其内部状态的方法,没有允许访问它所拥有的可变字段的方法。它也应该是final(因为BigDecimal应该是),以防止任何其他类扩展它,从而通过添加可变字段使其可变。

优势很多:

  • 课程很容易理解
  • 实例本质上是线程安全的
  • 可以缓存实例而无需从缓存中返回副本
  • 实例可以用作Map中的键,而不必担心在
  • 之后被更改

它不违反OO原则:相反,状态完全封装在对象中。

注意:一些不可变对象在内部更改其状态(例如,某些字段的延迟初始化),而不会影响对象的外部可见状态。如果操作正确,它不会改变不可变对象的线程安全性。如果操作不正确,可能会使它们不是线程安全的。

答案 2 :(得分:3)

BigDecimal是一个值类。它代表了“现实世界”的价值。我们以整数为例。 42总是值42.它的状态不能改变。如果我想拥有43,那么它不是42的改变值而是43的值。这个抽象概念的值通过使用不可变类在面向对象的世界中传递。如果要向现有数字添加数字,则不会更改数字,但会创建包含结果的新不可变对象。

答案 3 :(得分:1)

  

类的不变性意味着如果创建了对象,则无法更改其内容。

考虑例如

String str = "Hello"; // you can not change content Hello to any other string

immutability of a class - Pros. / Cons. of Immutability vs. Mutability

的利弊
  

扩展类可以变得可变吗?

是的,你可以做到。

  

MyBigDecimal extends BigDecimal

你可以做到BigDecimal不是最终的。