20

これはJava Concurrency in Practiceからの一文です

共有読み取り専用オブジェクトには、不変オブジェクトと事実上不変オブジェクトが含まれます。

不変オブジェクトと実質的に不変オブジェクトの違いは何ですか?

4

4 に答える 4

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();
    }
  }
}

のいくつかのインスタンスCは事実上不変であり、いくつかのインスタンスはそうではありません。

もう 1 つの例は、長さ 0 の配列です。変更可能な要素がないため、それらを含むクラスが証明可能な不変ではない場合でも、それらは事実上不変です。


Joe-E はベリファイアを使用して、一部のクラスが不変インスタンスのみを許可することを証明します。マーカー インターフェイスでマークされたImmutableものはすべてチェックされ、(エスケープしないためString実質的に不変) のような特定のクラスは不変として除外されます。char[]

Joe-E: Java のセキュリティ指向のサブセットは言う

Joe-E ライブラリによって定義された Immutable インターフェースは、言語によって特別に扱われます。Joe-E ベリファイアは、このインターフェースを実装するすべてのオブジェクトが (深く) 不変であることをチェックし、これが自動的に変更できない場合はコンパイル時エラーを発生させます。検証済み。

于 2013-05-21T20:03:51.003 に答える
10

これは、少しグーグルしてこの記事を見つけることからの私の理解です。効果的に不変なオブジェクトは、変更可能なフィールドを含むオブジェクトですが、それらのフィールドへの参照を提供しないため、それらのフィールドを変更することはできません。たとえば、 を含むクラスを作成するとしますArrayListArrayLists は可変ですが、クラスが常に 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);
   }
}

Pointオブジェクトは変更可能ですが、このクラスはそのPoint インスタンスへの直接参照を誰にも与えないため、問題ありません。代わりに、同じ値を持つ新しいインスタンスを返します。そうすれば、誰もLineクラスの状態を変更できなくなります。これにより、Lineクラスは事実上不変になります。

では、これは真の不変クラスとどう違うのでしょうか? 真に不変のクラスには、不変のフィールドもあります。Line本当に不変だったと想像してみましょう。Pointそのためには、それが不変であると想像する必要もあります。これらの仮定を行うと、getStart()メソッドは次のように記述できた可能性があります。

public Point getStart() {
   return start;
}
于 2013-05-21T20:03:07.377 に答える
2

この答えを見てください:

実質的に不変と不変 実質的に不変と不変の違いは、最初のケースでは、オブジェクトを安全な方法で公開する必要があることです。必要のない真に不変のオブジェクト用。したがって、真に不変なオブジェクトは公開しやすいため好まれます。前述の理由は、非同期公開を好む理由を示しています。

https://stackoverflow.com/a/7887675/1007546

于 2013-05-21T20:02:52.990 に答える