InternPool<T>
Javaでジェネリックを書くにはどうすればよいですか? Internable
インターフェイスは必要ですか?
String
Javaにはインターン機能があります。BigDecimal
やのようなクラスをインターンしたいですAccount
。
InternPool<T>
Javaでジェネリックを書くにはどうすればよいですか? Internable
インターフェイスは必要ですか?
String
Javaにはインターン機能があります。BigDecimal
やのようなクラスをインターンしたいですAccount
。
このようなもの:
public class InternPool<T> {
private WeakHashMap<T, WeakReference<T>> pool =
new WeakHashMap<T, WeakReference<T>>();
public synchronized T intern(T object) {
T res = null;
// (The loop is needed to deal with race
// conditions where the GC runs while we are
// accessing the 'pool' map or the 'ref' object.)
do {
WeakReference<T> ref = pool.get(object);
if (ref == null) {
ref = new WeakReference<T>(object);
pool.put(object, ref);
res = object;
} else {
res = ref.get();
}
} while (res == null);
return res;
}
}
equals
これは、を実装するプール要素クラスに依存し、hashCode
「値による等価性」を提供し、それらのメソッドの API コントラクトに従います。しかし、BigDecimal
確かにそうです。
更新WeakHashMap<T, WeakReference<T>>
-ではなく aが必要な理由の説明については、 javadocsWeakHashMap<T, T>
を参照してください。短いバージョンは、後者の主要な弱いリンクが GC によって壊れないということです。これは、対応するエントリ参照によって値が強く到達可能になっているためです。
ソリューションを2つのクラスに分けて、コードをよりクリーンにし、この方法でループを取り除きます。
public class WeakPool<T> {
private final WeakHashMap<T, WeakReference<T>> pool = new WeakHashMap<T, WeakReference<T>>();
public T get(T object) {
final T res;
WeakReference<T> ref = pool.get(object);
if (ref != null) {
res = ref.get();
} else {
res = null;
}
return res;
}
public void put(T object) {
pool.put(object, new WeakReference<T>(object));
}
}
そして、弱いプールを使用するインターン クラスは非常に単純です。
public class InternPool<T> {
private final WeakPool<T> pool = new WeakPool<T>();
public synchronized T intern(T object) {
T res = pool.get(object);
if (res == null) {
pool.put(object);
res = object;
}
return res;
}
}
これは、 flyweight patternを探しているように聞こえます。
Flyweightはソフトウェア設計パターンです。flyweight は、他の同様のオブジェクトとできるだけ多くのデータを共有することによって、メモリの使用を最小限に抑えるオブジェクトです。
リンクをクリックすると、Java の例が含まれています。
すべきではない
"WeakReference ref = プール.get(オブジェクト);"
代わりに
WeakReference ref = プール.インターン(オブジェクト);
??