Я использую LazyReference
класс в течение нескольких лет (конечно, не регулярно, но иногда это очень полезно). Класс можно увидеть здесь . Кредиты поступают к Робби Ванбрабанту (автору класса) и Джошуа Блоху с его знаменитым «Effective Java 2nd edt». (оригинальный код).
Класс работает правильно (в Java 5+), но есть одна небольшая потенциальная проблема. Если instanceProvider
возвращает null
(что не обязательно в соответствии с контрактом Guice Provider.get()
, но ...), то при каждом выполнении метода LazyReference.get()
LOCK будет удерживаться и instanceProvider.get
будет вызываться снова и снова. Это выглядит хорошим наказанием для тех, кто нарушает контракты (хе-хе), но что, если действительно нужно лениво инициализировать поле с возможностью установить значение 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
)? Будет ли он работать правильно?