不可变和有效不可变对象之间的区别?

she*_*aei 20 java multithreading

这是Java Concurrency in Practice中的一句话

共享只读对象包括不可变和有效不可变对象.

不可变和有效不可变对象之间有什么区别?

Mik*_*uel 15

不可扩展且其字段全部final且本身不可变的类的实例是不可变的.

由于其方法的细节而无法变异的类的实例实际上是不可变的.例如:

final class C {
  final boolean canChange;
  private int x;
  C(boolean canChange) { this.canChange = canChange; }
  public void setX(int newX) {
    if (canChange) {
      this.x = newX;
    } else {
      throw new IllegalStateException();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

有些实例C是有效不可变的,有些则不是.

另一个例子是零长度数组.它们实际上是不可变的,即使它们的包含类不可证明是不可变的,因为它们中没有可以改变的元素.


Joe-E使用验证程序来证明某些类仅允许不可变实例.任何标记有Immutable标记接口的东西都会被检查,并且某些类String(因为它char[]不会逃脱而有效地不可变)会被视为不可变的.

Joe-E:一个面向安全的Java子集

由Joe-E库定义的Immutable接口由语言专门处理:Joe-E veri fi er检查实现此接口的每个对象是否(深度)不可变,如果不能自动生成,则会引发编译时错误VERI网络版.


Dan*_*lan 10

这是我从谷歌搜索和发现这篇文章的理解.一个有效不可变的对象是一个包含可以变异的字段的对象,但它不会让任何东西改变这些字段,因为它永远不会给你一个引用.例如,假设您创建了一个包含ArrayListin 的类. ArrayLists是可变的,但是如果你的类总是返回一个ArrayList的副本,并且你的类中的其他所有内容都是不可变的,那么你的类已经变得有效不可变:没有办法改变你的类的实例的状态.

博客文章将此作为有效不可变类的示例:

import java.awt.*;

public class Line {

   private final Point start;
   private final Point end;

   public Line(final Point start, final Point end) {
       this.start = new Point(start);
       this.end = new Point(end);
   }

   public void draw() {
       //...
   }

   public Point getStart() {
       return new Point(start);
   }

   public Point getEnd() {
       return new Point(end);
   }
}
Run Code Online (Sandbox Code Playgroud)

Point对象是可变的,但没关系,因为这个类没有给任何人直接引用它的 Point实例.相反,它返回一个具有相同值的新实例.这样,没有人可以改变Line班级的状态.这使得Line该类有效地不可变.

那么这与一个真正不可改变的阶级有什么不同呢?一个真正不可变的类具有也是不可变的字段.让我们想象一下Line真的是一成不变的.要做到这一点,我们也必须想象这Point是不可改变的.做出这些假设,该getStart()方法可以这样编写:

public Point getStart() {
   return start;
}
Run Code Online (Sandbox Code Playgroud)