Ну, концепция читает JLS и понимает ее. В этом случае JLS говорит:
Конечные поля также позволяют программистам реализовать поточно-безопасные неизменяемые объекты без синхронизации. Нитебезопасный неизменяемый объект рассматривается как непреложный для всех потоков, даже если гонка данных используется для передачи ссылок на неизменяемый объект между потоками. Это может обеспечить гарантии безопасности от неправильного использования неизменяемого класса с помощью неправильного или вредоносного кода. конечные поля должны использоваться правильно, чтобы обеспечить гарантию неизменности.
Модель использования конечных полей является простой: установите конечные поля для объекта в конструкторе этого объекта; и не записывайте ссылку на объект, который строится в месте, где другой поток может видеть его до завершения конструктора объекта. Если это произойдет, тогда, когда объект будет замечен другим потоком, этот поток всегда будет видеть правильно построенную версию окончательных полей этого объекта. Он также будет видеть версии любого объекта или массива, на которые ссылаются те последние поля, которые, по крайней мере, соответствуют последним, как конечные поля.
Так что вам нужно:
- Сделать
address
как окончательный и частные.
- Для любого изменяемого объекта вы должны препятствовать тому, чтобы ссылка на этот объект отображалась снаружи.
В этом случае # 2, вероятно, означает, что вы не можете вернуть ссылку на адрес, как у вас, с getAddress()
. И вам нужно сделать защитную копию. I.e., сделайте копию объекта и сохраните копию в Employee. Если вы не можете сделать оборонительную копию, то действительно невозможно сделать Работника неизменным.
public final class Employee{
private final int id;
private final Address address;
public Employee(int id, Address address)
{
this.id = id;
this.address=new Address(); // defensive copy
this.address.setStreet(address.getStreet());
}
pulbic int getId(){
return id;
}
public Address getAddress() {
Address nuAdd = new Address(); // must copy here too
nuAdd.setStreet(address.getStreet());
return nuAdd;
}
Реализация clone()
или что-то подобное (копия CTOR) сделает создание оборонительных объектов проще для сложных классов. Тем не менее, лучшая рекомендация, я думаю, будет заключаться в том, чтобы сделать Address
неизменяемым. Как только вы это сделаете, вы сможете свободно обходить свою ссылку без каких-либо проблем с обеспечением безопасности потоков.
В этом примере обратите внимание, что я делаю NOT необходимо скопировать значение street
. Street
- это строка, и строки неизменяемы.Если street
состоял из изменчивых полей (например, число целых улиц), то I было бы также сделать копию street
также и так далее до бесконечности. Вот почему неизменяемые объекты настолько ценны, что они разрушают цепочку «бесконечной копии».
'Employee' не является неизменным, и там не так много вы можете сделать, чтобы изменить это, если вы не можете изменить' Address' класс для поддержки при минимальном копировании, но предпочтительно сделать «адрес» неизменным в первую очередь. –