1

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

4

4 回答 4

3

“这些物品给我们带来了什么好处”您已经回答了这个问题。

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

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

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

于 2012-07-02T13:01:43.990 回答
2

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

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

于 2012-07-02T13:06:55.717 回答
0

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

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

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

假设你有一个像国家代码这样的静态对象的全局缓存,你可以在这里申请Immutability

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

于 2012-07-02T13:03:18.327 回答
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
}

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

于 2012-07-02T19:23:12.603 回答