2013-05-21 10 views
18

これは、共有は読み取り専用オブジェクトは不変かつ効果的に不変 オブジェクトを含む実践不変オブジェクトと実効不変オブジェクトの違いは?

でJava並行処理からの文です。

不変オブジェクトと効果的不変オブジェクトの違いは何ですか?

+0

あなたが参照する本にも言及する[効果的に不変なオブジェクトが意味をなす](http://stackoverflow.com/questions/8707426/do-effectively-immutable-objects-make-sense)を参照してください。 – Bobulous

+0

も参照してください[不変オブジェクトのすべてのプロパティを最終にする必要がありますか?](http://stackoverflow.com/questions/16061030/must-all-properties-of-an-immutable-object-be-final) – assylias

答えて

14

インスタンス:これらの仮定を作る、getStart()方法は次のように書くことができたかもしれません。

メソッドの詳細からフィールドを変更できないクラスのインスタンスは、効果的に変更できません。たとえば:

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つの例は、長さゼロの配列です。これらのクラスは、変更可能な要素がないため、その包含クラスが不変であるとは限りませんが、実質的に不変です。


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

Joe-E: A Security-Oriented Subset of Javaは不変インターフェイス、ジョー-Eライブラリによって定義さドFiの が言語によって特別に処理され

言う:ジョー・E VERIのfi ERこのインタフェースを実装するすべてのオブジェクトが 深く(あろう チェックが)不変であり、 が自動的に検証されない場合、コンパイル時エラーが発生します。

+0

"フィールドのメソッドの詳細のためにフィールドを変更できないクラスのインスタンスは事実上不変です" - これは不正確です。 _効果的にImmutable_は、_safleyが公開された後に変更されていない限り任意のオブジェクトにすることができます(例えば、揮発性参照などを介して) –

+0

@OpDeCirkel、 "immutable"の-able接尾辞は、変異していない。 Goetzらが意図した意味ではないという明白な情報があれば、回答を追加してください。私はupvoteします。 –

+0

JCP 3.5.4:技術的に不変ではないが、発行後に状態*が変更されないオブジェクトは効果的に不変と呼ばれる。 - この定義には、状態を変更するメソッドを持たないオブジェクトがより広範に含まれています。安全な出版の後にオブジェクトを変異させてはならないというコンビニエンスだけで、事実上不変であることができます。 –

2

は、この答えを見てみましょう:

効果的に不変で不変の効果的不変と不変の違いは最初のケースでは、あなたがまだ安全な方法でオブジェクトを公開する必要があるということです。必要のない本当に不変なオブジェクトの場合。なぜなら、私が上で述べた理由は、あなたが非同期の出版を好むかもしれない理由を述べているからです。

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

6

ここでグーグルとthis articleを見つけるのビットからの私の理解です。効果的に変更不能なオブジェクトは、変更可能なフィールドを含むオブジェクトですが、フィールドへの参照が決して与えられないため、これらのフィールドを変更することはできません。たとえば、ArrayListのクラスを作成するとします。 ArrayListは変更可能ですが、クラスが常に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オブジェクトは変更可能ですが、それは大丈夫だ、このクラスは誰にへの直接参照を与えるものではありませんので、それはポイントのインスタンスです。代わりに、同じ値を持つ新しいインスタンスを返します。そうすれば、誰もLineクラスの状態を変更することはできません。これにより、Lineクラスは効果的に不変になります。

これは本当に不変なクラスとどのように違うのですか?本当に不変なクラスには、不変のフィールドもあります。想像してみましょうLineは本当に不変でした。これを行うには、Pointが不変であると想像しなければなりません。拡張性とそのフィールドのすべてのfinalと自身不変不変ではなく、クラスの

public Point getStart() { 
    return start; 
} 
+0

@Gray参照私の編集、ありがとう –

+0

用語はさまざまですが、タイプではなくオブジェクト*インスタンス*の特性として「効果的な不変性」を考えます。特定のインスタンスへの参照が変更される可能性のあるコードに公開される可能性のある実行パスが存在しない場合、クラスがそうでなくても、そのインスタンスは事実上不変である。私は不変型または効果的に不変のインスタンスの値と参照のみを保持するオブジェクトを検討し、それ自体の形状を変更するメソッドは公開しません。 – supercat

+0

@スパーキャットは、フレーズの英語の意味からは意味があります。 –

1

不変オブジェクトは完全にその内部状態をカプセル化し、それらが共有オブジェクトからの読み出しであるので、したがって、彼らは複数のスレッド間で共有することが安全である(ETC、おそらく最終の使用により)構築した後、その状態の変更を許可しません複数のスレッドからは害を受けません。

効果的に変更不能なオブジェクトは、複数のスレッド間で共有される前に状態が変更される可能性がありますが、「公開」された後に変更される可能性があります。

不変オブジェクトを使用すると、遅延初期化のような有用なソフトウェアエンジニアリングの慣行を使用できなくなります。プロパティやフィールドを遅延させるためには、可変である必要があります。効果的に不変なオブジェクトは、内部状態を安全に変更できる時期と禁止されている時期を注意深く知ることによって、これらの制約を緩和して、両方の世界のアプローチを最大限に活用します。

+0

はい文字列は不変であり、内部状態を直接変更できないようにしますが、ハッシュコードを計算するときには遅延初期化を使用します。技術的にStringは事実上不変です。 – chubbsondubs

関連する問題