クライアントがこれらのメソッドによって返される参照を介してのみコレクションにアクセスし、直接ではない場合、コレクションを不変にするなどのラッパーメソッドCollections#unmodifiableSet
やその他のバリエーションがあることを私は知っています。しかし、コレクション内の個々のオブジェクトが不変になるのを防ぎますか?Google GuavaのようなAPIではなく、標準のJDKクラスを使用して同じことを達成できますか?Collections#unmodifiableMap
Collections#unmodifiableList
4 に答える
いいえ、クラスの不変バージョンを作成する必要があります。
サンプル :
List< StringBuilder > l1 = new LinkedList< StringBuilder >();
l1.add( new StringBuilder()); // ok
List< StringBuilder > l2 = Collections.unmodiableList( l1 );
l2.get(0).append( "Hello" ); // ok, because StringBuilder, unlike String is mutable
l2.add( new StringBuilder()); // throws exception
私があなたの目標を理解していれば。あなたはこのようなものを使うことができます
class Wraper<T>{
List<T> list = new ArrayList<T>(); //Other Collection?
T someObj = getYourInstance();
public T get(int index) {
T obj = list.get(index);
if (obj.equals(someObj)){//should be overriden
return createInstanceOf(obj);
} else {
return obj;
}
}
}
const
Javaと同等のものを求めています。これは不可能です。これは、Java の拡張機能として (私自身を含む) 多くのユーザーから長年にわたって要求されてきました。それは閉鎖され、Sun によって拒否されました。
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070
これを行いたい場合は、可変フラグをオブジェクトに組み込む必要があります (おそらく構築時に)。そして、すべてのミューテーター メソッドで、mutability フラグを確認します。おそらく、CGLIB などのプロキシ ライブラリを使用してもっと「派手な」ことを行うことができるかもしれませんが、達成しようとしているものに対しては過度に複雑になる可能性があります。
そのように設計されていないクラスを不変にすることを考えることができる唯一の方法は、プロキシでラップすることです。その後、変更メソッドの制御にアクセスできます。
すなわち。
MyClass {
private int anInt;
public void setInt(int a) {
anInt = a;
}
public int getInt() {
return anInt;
}
...
その後
MyProxy {
private MyClass myClass = ...;
public int getInt() {
return myClass.getInt();
}
...
等々。
リフレクションを介して同じことを達成することもできます (Spring が Bean をラップし、通常はプロキシとのみ対話するのと同じ方法で)
ただし、クライアントが実際の基になるクラス (この例では MyClass) を取得した場合、内部を変更できるとは限りません。クライアントに見せる「変更可能な」ラッパーを公開する以外に、これを直接停止する実際の方法はありません