Допустим, у меня есть следующий класс
public class A {
private B b;
}
Теперь есть фабрика для создания экземпляров B, но метод создателя выдает исключение
public class BCreatorFactory {
public static createB() throws SomeException {
// DO the intialization
// ...
return b;
}
, если я установилAb в строке объявления, тогда у меня не было бы никакого способа обработать исключение
public class A {
private B b = BCreatorFactory.createB() // BAD -> no way of dealing with the exception
}
, если бы я установил Ab в конструкторе, то у меня либо «наполовину испеченный» экземпляр, либо я снова выбрасываю исключение и форсируювызов кода для обработки неправильно инициализированного экземпляра
public class A {
private B b;
public A() {
try {
b = BCreatorFactory.createB();
}
catch (SomeException se) {
// Do something, perhaps try to recover ? <- IMO also BAD
}
}
}
или
public class A {
private B b;
public A() throws SomeException { // BAD
b = BCreatorFactory.createB();
}
}
Я мог бы попытаться отложить экземпляр init B:
public class A {
private B b;
public B getB() throws SomeException {
if (b == null) {
b = BCreatorFactory.createB(); // BAD -> not thread safe -> can result in redundant createB() invocations
}
return b;
}
}
Но единственный способЯ могу подумать о том, чтобы сделать его поточно-безопасным с помощью , который, как известно, был взломан в JVM java Двойная проверка блокировки
public class A {
private B b;
public B getB() throws SomeException {
if (b == null) {
synchronized(this) {
if (b == null) {
b = BCreatorFactory.createB(); // BAD -> not really thread safe -> broken
}
}
}
return b;
}
}
Что тогда, уважаемый пациент-читатель,что мне делать?
Другими словами, Каково наилучшее решение для инициализации экземпляра объекта, который содержит ссылку на объект, создание которого может вызвать исключение?