4

現在、マルチスレッド フレームワークを開発しています。副作用を避けるために、フレームワークによって操作されるすべてのデータが不変でなければならないことを要求したいと思います。

特定のクラスのすべてのサブクラスまたは特定のインターフェイスを実装するすべてのクラスを不変にするように指定する方法がJavaに存在しますか?

4

3 に答える 3

3

MutabilityDetectorを調べることをお勧めします。静的分析を実行して、特定のクラスが不変であるかどうかを判断します。これは、ランタイムアサーションに似たものを追加するために使用できます。つまり、可変クラスのインスタンスが渡された場合に例外をスローすることを選択できます。定義したインターフェースのサブクラスや実装を含め、実行時に実際の具体的なクラスを分析できることに注意してください。

これはまだ1.0より前のリリースであり、に問題がありますがjava.lang.String、使用できる可能性があります。探しているものに近いが、期待どおりの結果が得られない場合は、プロジェクトメンテナが非常に合理的な人物であると信じているため、メーリングリストに連絡するかバグレポートを提出することをお勧めします。免責事項:そのメンテナは私です;-)

于 2012-07-04T21:42:22.617 に答える
2

サブクラスの不変性を要求する方法はありません。セッターを提供せず、インスタンス変数を非公開にすることで、クラスのサブクラスが状態を変更しないようにすることができますが、サブクラスが独自のインスタンス変数を宣言する場合、サブクラスはそれらを完全に制御できます。

インターフェイスに関する限り、できることはセッターを提供しないことだけです。ただし、実装は独自のセッターを提供できます。

于 2012-07-04T00:30:01.663 に答える
1

クラスを真に不変にするには、クラスのすべてのメンバーが不変であり、クラス自体がfinal. これにより、クラス内またはクラス外からオブジェクトを変更できなくなります。

クラス内のメンバーを不変にするということは、単にメンバーを変更する以上のことを意味しますfinal。例えば

private final List<String> strings = new LinkedList<String>();

stringsただし、項目はfinalリストに追加および削除できるため、変更することができます。この場合、変更不可能なコレクションにラップできます。リスト内のオブジェクトは変更可能である可能性があるため、これでも完璧ではありませStringsん(明らかにではありませんが、リストには変更可能なオブジェクトが含まれている可能性がありますlist.get(index).mutator(...)

オブジェクトを不変にする方法について特効薬はありません。オブジェクトを変更するメソッドを提供する場合、不変にすることはできません。

class の作成に関しては、final保証された不変性を実現するためにこれが必要です。ケースを想像して、

class MyImmutableClass {
    private final String name
}

class MutableClass extends MyImmutableClass {
    private String mutableValue;

    public void setMutableValue(String mutableValue...)
}

void doSomething(MyImmutableClass c) {...}

doSomethingが実際に不変インスタンスを処理しているという保証はありませんが、可変サブクラスを処理している可能性があります。ご覧のとおり、これはインターフェイスを操作する際に問題を引き起こします。インターフェイスの実装者が不変であることを保証する方法はありません。

注釈は不変性を保証する@Immutableものではなく、クラスが不変であることを伝えているだけですが、それを強制する良い方法はありません。

groovy で作業できる場合、@Immutable注釈は上記の多くのテクニックを実行するため、何らかの効果があります。http://groovy.codehaus.org/Immutable+AST+Macro

于 2012-07-04T22:04:25.433 に答える