2012-07-02 24 views
1

我知道不可变对象总是具有相同的状态,它们是实际创建的状态。它们的不变式由构造函数建立,并且由于它们的状态在构建之后不会改变,所以这些不变量总是保持良好,这就是为什么它们可以安全地在多线程环境中发布的原因。这一切都很好,但是因为我们生活在一个动态的世界中,程序状态不断变化,所以如果我们通过不可变的对象构造我们的程序状态,这些对象会给我们带来什么好处?当程序状态不断变化时不可变对象的用处

+0

这里是另一篇文章,可能有你的问题的答案:http://stackoverflow.com/questions/214714/mutablevs-immutable-objects –

+0

不变的对象就像事实。事实不会改变,但你总是可以'制造'新的。 – Stefan

回答

3

“这样的物体给我们带来了什么好处”,您已经回答了这个问题。

关于你的问题的“动态”的一部分,如果你需要“变革”不可变对象,你可以创建一个从旧的一个新问题:

Immutable oldObj = new Immutable(...); 
Immutable newObj = new Immutable(oldObj.property1, "a new value for property 2"); 

如果你发现你继续做反复,那么也许你需要使对象变为可变的,并添加需要能够在并发环境中使用该对象的相关胎面安全功能。

0

Immutable objects当你需要一些静态对象,它的状态永不改变时,它是非常有用的。最大的优点是不变性,对象语义和智能指针使对象所有权成为一个争论点。隐含地,这也意味着存在并发时的确定性行为。

的Java已经定义了一些不可改变的类,如StringInteger

其他好处是它们总是具有“失败原子性”(Joshua Bloch使用的一个术语):如果一个不可变对象抛出一个异常,它永远不会处于不受欢迎或不确定的状态。如果你有一个像国家代码静态对象的全局缓存

让说,在这里你可以申请Immutability

Why do we need immutable class?

+0

不仅不可变对象本身具有失败的原子性,而且这种原子性通常延伸到这些对象的可变持有者。如果我'Fnord'是一个不可变的类,并且一个对象具有该类类型的字段'foo',那么就像'foo = foo.WithWizzleAndWozzle(5,3);'[这应该有效地改变'foo的值.Wizzle'设置为5,'foo.Wozzle'设为3]可以改变两个值,也可以不改变。如果不改变另一个,就无法改变它。 – supercat

2

不可变对象让你清晰地传达状态变化到不同的线程。

它是使用不可变对象来表示线程之间交换的消息一个好的做法。一旦发送了这样的消息,其有效负载就不能被改变,从而防止了许多并发相关的错误。如果一个线程需要传达一些进一步的变化,它只会发送下一个消息。

0

不可变对象是在这样的情况下非常有用,用一个String对象:

public class A { 
    private volatile String currentName = "The First Name"; 

    public String getCurrentName() { 
     // Fast: no synching or blocking! Can be called billions of times by 
     // billions of threads with no trouble. 
     // (Does need to be read from memory always because it's volatile.) 
     return currentName; 
    } 
    public whatever someMethod() { 
     ... code ... 
     // Simple assignment in this case. Could involve synchronization 
     // and lots of calculations, but it's called a lot less than 
     // getCurrentName(). 
     currentName = newName; 
     ... code ... 
    } 
} 
public class B { 
     ... in some method ... 
     A objA = something; 
     // Gets "name" fast despite a billion other threads doing the same thing. 
     String name = objA.getCurrentName(); 
     // From this point on, String referenced by "name" won't change 
     // regardless of how many times A.currentName changes. 
     ... code with frequent references to objA 
} 

这使得复杂的数据(或者甚至是简单的数据,这种情况下),必须是一致的(如果不是正好先进-date)被更新并以线程安全的方式非常快速地传递给任何想要它的人。数据传输很快变得过时,也许,但调用方法时它保持其价值,并保持一致。