Недостаток JavaBean - несовместим при создании
Эффективная Java - состояния Item-2,
JavaBean может находиться в несогласованном состоянии в процессе своего построения.
Я не мог понять это, если объект создается в методе, как это может быть противоречивым, если исключение должно произойти, что может произойти и в конструкторе. И как это связано с многопоточностью?
2 ответа
Следующий бин был представлен в книге:
NutritionFacts cocaCola = new NutritionFacts();
cocaCola.setServingSize(240);
cocaCola.setServings(8);
cocaCola.setCalories(100);
cocaCola.setSodium(35);
cocaCola.setCarbohydrate(27);
из них servingSize
а также servings
установить с помощью setServingSize(int)
а также setServings(int)
фундаментальные - по крайней мере, в книге - для фактов питания.
Но если вы просто позвоните:
NutritionFacts cocaCola = new NutritionFacts();
cocaCola.setServingSize(240);
cocaCola.setCalories(100);
тогда servings
поле не будет установлено. Таким образом, полученный экземпляр теперь находится в недопустимом состоянии.
Так что если вы хотите вызвать метод, который ожидает действительный экземпляр, скажем, healthRiskCalculator.calculateHealthRisk(NutritionFacts facts)
тогда вы получите исключение либо внутри объекта, либо в healthRiskCalculator
,
Так что теперь вы можете проверить ущерб вашему здоровью, когда вы звоните calculateHealthRisk()
но может быть много методов, которые читают или используют экземпляр объекта. Кроме того, вы, возможно, создали много недействительных экземпляров и для других продуктов. Другими словами, это не быстро провалится.
Таким образом, не существует надежного способа создания построенного объекта с использованием bean-компонентов. Это не относится к многопоточности, вы можете создать недопустимый экземпляр компонента в одном потоке.
Представьте себе резьбовую модель, где ThreadUtils.doFoo(FooBean fb)
будет порождать поток, который будет работать с fb
, fb
может быть таким же простым, как и параметры, передаваемые этому потоку для определения его вычисления. Теперь возьмите следующий конструктор:
public FooBean(int i, int j, int k, int l, int port){
ThreadUtils.doFoo(this);
someListField = Arrays.asList(i, j, k, l);
this.port = port;
}
Это вызывает this
просочиться из конструктора. Если по какой-то ложной причине порожденный поток действовал до того, как список был должным образом создан и назначен, у вас будет поток, работающий в несовместимом состоянии: this
, Если, например, port
был использован новым потоком для прослушивания сокета, и this
В случае утечки сокет может прослушивать порт 0 (значение по умолчанию для числового поля), а не порт. port
,
На самом деле, исключение в конструкторе может быть проблемой, если this
протекает и получает доступную сильную ссылку из других мест.
Тем не менее, следующий конструктор безопасен:
public FooBean(int i, int j, int k, int l, int port){
someListField = Arrays.asList(i, j, k, l);
this.port = port;
ThreadUtils.doFoo(this);
}
Это связано с тем, что в модели памяти Java поля сохраняются до того, как поток даже будет создан.