現在、マルチスレッド フレームワークを開発しています。副作用を避けるために、フレームワークによって操作されるすべてのデータが不変でなければならないことを要求したいと思います。
特定のクラスのすべてのサブクラスまたは特定のインターフェイスを実装するすべてのクラスを不変にするように指定する方法がJavaに存在しますか?
現在、マルチスレッド フレームワークを開発しています。副作用を避けるために、フレームワークによって操作されるすべてのデータが不変でなければならないことを要求したいと思います。
特定のクラスのすべてのサブクラスまたは特定のインターフェイスを実装するすべてのクラスを不変にするように指定する方法がJavaに存在しますか?
MutabilityDetectorを調べることをお勧めします。静的分析を実行して、特定のクラスが不変であるかどうかを判断します。これは、ランタイムアサーションに似たものを追加するために使用できます。つまり、可変クラスのインスタンスが渡された場合に例外をスローすることを選択できます。定義したインターフェースのサブクラスや実装を含め、実行時に実際の具体的なクラスを分析できることに注意してください。
これはまだ1.0より前のリリースであり、に問題がありますがjava.lang.String
、使用できる可能性があります。探しているものに近いが、期待どおりの結果が得られない場合は、プロジェクトメンテナが非常に合理的な人物であると信じているため、メーリングリストに連絡するかバグレポートを提出することをお勧めします。免責事項:そのメンテナは私です;-)
サブクラスの不変性を要求する方法はありません。セッターを提供せず、インスタンス変数を非公開にすることで、クラスのサブクラスが状態を変更しないようにすることができますが、サブクラスが独自のインスタンス変数を宣言する場合、サブクラスはそれらを完全に制御できます。
インターフェイスに関する限り、できることはセッターを提供しないことだけです。ただし、実装は独自のセッターを提供できます。
クラスを真に不変にするには、クラスのすべてのメンバーが不変であり、クラス自体が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