我已经使用LazyReference
类几年了(当然不是定期使用,但有时它非常有用)。课程可以在这里看到。归功于 Robbie Vanbrabant(课程作者)和 Joshua Bloch 以及他著名的“Effective Java 2nd edt”。(原始代码)。
该类可以正常工作(在 Java 5+ 中),但存在一个小问题。如果instanceProvider
返回null
(当然它不能根据 GuiceProvider.get()
合同,但是......)然后在每次执行LazyReference.get()
方法时,LOCK 将被持有并被instanceProvider.get
一遍又一遍地调用。对于那些违反合同的人来说,这似乎是一种很好的惩罚(he-he),但如果真的需要懒惰地初始化一个可以设置null
值的字段怎么办?
我稍微修改了 LazyReference:
public class LazyReference<T> {
private final Object LOCK = new Object();
private volatile T instance;
private volatile boolean isNull;
private final Provider<T> instanceProvider;
private LazyReference(Provider<T> instanceProvider) {
this.instanceProvider = instanceProvider;
}
public T get() {
T result = instance;
if (result == null && !isNull) {
synchronized (LOCK) {
result = instance;
if (result == null && !isNull) {
instance = result = instanceProvider.get();
isNull = (result == null);
}
}
}
return result;
}
}
恕我直言,它应该可以正常工作(如果您有其他意见,请发表您的评论和批评)。但是我想知道如果我volatile
从布尔值中删除修饰符会发生什么isNull
(当然保留它instance
)?它还能正常工作吗?