当程序的状态不断变化时,不可变对象的有用性



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

"

这些对象给我们带来了什么好处"你已经回答了。

关于问题的"动态"部分,如果您需要"更改"一个不可变的对象,您可以从旧对象创建一个新对象:

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

如果您发现您一直在重复这样做,那么您可能需要使对象可变,并添加能够在并发环境中使用该对象所需的相关胎面安全功能。

不可变对象允许您将状态更改干净地传达给不同的线程。

最好

使用不可变对象来表示线程之间交换的消息。发送此类消息后,其有效负载将无法更改,从而防止了许多与并发相关的错误。如果线程需要传达一些进一步的更改,它只会发送下一条消息。

当您

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

Java已经定义了一些不可变类,如String Integer

另一个好处是它们总是具有"失败原子性"(Joshua Bloch使用的术语):如果一个不可变的对象抛出异常,它永远不会处于不希望或不确定的状态。

假设您有一个静态对象的全局缓存,例如 国家代码 ,在这里您可以应用 Immutability .

为什么我们需要不可变的类?

不可变对象在这样的情况下非常有用,使用 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
}

这允许必须一致(如果不是精确更新)的复杂数据(甚至简单数据,在这种情况下)更新并以线程安全的方式非常快速地交付给任何想要它的人。 传递的数据可能很快就会过时,但它将在调用方法期间保持其值并保持一致。

最新更新