Поля должны быть явно окончательными, чтобы иметь “надлежащий” неизменный объект?

Вы часто читаете о неизменных объектах, требующих, чтобы заключительные поля были неизменны в Java. Этот на самом деле имеет место, или это достаточно просто, чтобы не иметь никакой общедоступной переменчивости и не на самом деле видоизменить состояние?

Например, если Вам создал неизменный объект шаблон разработчика, Вы могли бы сделать это при наличии разработчика, присваивают отдельные поля, поскольку он создает, или наличие разработчика содержит поля само и в конечном счете возвращает неизменный объект путем передачи значений его (частному) конструктору.

Наличие полевого финала имеет очевидное преимущество предотвращения ошибок реализации (таких как разрешение кода сохранить ссылку на разработчика и "создание" объекта многократно, на самом деле видоизменяя существующий объект), но имение Разработчика хранит свои данные в объекте, поскольку это создается, казалось бы, был бы СУШИЛКОЙ.

Таким образом, вопрос: Принятие Разработчика не пропускает Объект рано и мешает себе изменить объект, однажды созданный (скажите путем установки его ссылки на объект, столь же пустой) есть ли на самом деле что-либо полученное (такое как улучшенная потокобезопасность) в "неизменности" объекта, если поля объекта были сделаны окончательными вместо этого?

5
задан Yishai 17 May 2010 в 22:43
поделиться

4 ответа

Да, вы получаете «потокобезопасность» из полей final . То есть значение, присвоенное полю final во время построения, гарантированно будет видимым для всех потоков.Другой альтернативой для обеспечения безопасности потоков является объявление полей volatile , но тогда вы несете большие накладные расходы при каждом чтении… и сбиваете с толку любого, кто смотрит на ваш класс и задается вопросом, почему поля этого «неизменного» класса помечены как «летучие».

Отметка полей final является наиболее правильной с технической точки зрения и наиболее четко передает ваши намерения. К сожалению, это делает конструктор очень громоздким. Я думаю, что должна быть возможность создать обработчик аннотаций для синтеза компоновщика для неизменяемого класса, во многом так же, как Project Lombok делает с сеттерами и геттерами. Настоящая работа будет заключаться в поддержке IDE, необходимой для того, чтобы вы могли кодировать против сборщиков, которых на самом деле не существует.

6
ответ дан 14 December 2019 в 04:32
поделиться

Объект, безусловно, может иметь изменяемые закрытые поля и по-прежнему работать как неизменяемый объект. Все, что имеет значение для выполнения контракта неизменности, это то, что объект кажется неизменным извне. Например, объект с нефинальными закрытыми полями, но без сеттеров, удовлетворит этому требованию.

На самом деле, если ваша инкапсуляция правильная, то вы можете фактически мутировать внутреннее состояние и по-прежнему успешно работать как «неизменяемый» объект. Примером может быть какая-то ленивая оценка или кэширование структур данных.

Clojure, например, делает это в своей внутренней реализации ленивых последовательностей, эти объекты ведут себя так, как будто они неизменяемы, но фактически вычисляют и хранят будущие значения только тогда, когда они непосредственно запрашиваются. Любой последующий запрос извлекает сохраненное значение.

Однако - я бы добавил в качестве предостережения, что количество мест, где вы действительно хотели бы мутировать внутренности неизменяемого объекта, вероятно, довольно редко. Если вы сомневаетесь,сделать их окончательными.

2
ответ дан 14 December 2019 в 04:32
поделиться

Я думаю, вам просто нужно рассмотреть среду, в которой он работает, и решить, не представляют ли опасности фреймворки, использующие отражение для управления объектами.

Можно легко придумать необычный сценарий, в котором якобы неизменяемый объект будет уничтожен посредством атаки POST-инъекции из-за инфраструктуры привязки веб-страниц, которая настроена на использование отражения вместо установщиков bean-компонентов.

0
ответ дан 14 December 2019 в 04:32
поделиться

Вы определенно можете иметь неизменяемый объект с не конечными полями.

Например, смотрите реализацию java 1.6 java.lang.String.

0
ответ дан 14 December 2019 в 04:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: