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
肯定会。
更新- 关于为什么我们需要 aWeakHashMap<T, WeakReference<T>>
而不是 a的解释WeakHashMap<T, T>
,请参阅javadocs。简短的版本是后者中的关键弱链接不会被 GC 破坏,因为相应的条目引用使这些值具有强可达性。
我会将解决方案分为两个类以拥有更清晰的代码,并以此摆脱循环:
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;
}
}
只是一个快速警告:
上面没有明确提到,但是很明显,被实习的对象 必须是不可变的类型。
第二个注意事项:您不需要使用对该对象的另一个弱引用作为映射中的值,如果您仅依赖映射的数据键集,则对静态的引用就足够了。例如,声明:
WeakHashMap<T,Boolean>
并插入对:
pool.put (object, Boolean.TRUE);
这是对 WeakReference 实例的少量保存(如果您不能重用用于密钥的实例)。
...或者创建一个 WeakSet 类,就像@PeterVerhas 对他的 WeakPool 所做的那样。
不应该
“弱引用 ref = pool.get(object);”
而是
弱引用 ref = pool.intern(object);
??